Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSE: Include symbolic contracts corresponding to contract fields into accounts #600

Merged
merged 45 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
43878bb
Draft implementation and test for `contract` field accounts inclusion
palinatolmach Jun 5, 2024
8010577
Set Version: 0.1.301
Jun 5, 2024
1a929bc
Merge branch 'master' into cse-contract-fields
PetarMax Jun 5, 2024
e3794f8
Set Version: 0.1.301
Jun 5, 2024
0c6a57e
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 6, 2024
a78dbb6
Set Version: 0.1.302
Jun 6, 2024
6092452
Use (simple) `#lookup` constraint for `contract` field in storage
palinatolmach Jun 6, 2024
fcd95fa
Minor formatting
palinatolmach Jun 6, 2024
6ac1afa
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 7, 2024
a336d15
Set Version: 0.1.303
Jun 7, 2024
47f1263
Draft implementation refactoring
palinatolmach Jun 7, 2024
486d848
Merge branch 'master' into cse-contract-fields
PetarMax Jun 8, 2024
8bae8cf
Set Version: 0.1.306
Jun 8, 2024
b8aa43c
renaming contracts to avoid conflicts, removing unneeded constraints
PetarMax Jun 8, 2024
1c5795d
minor streamlining
PetarMax Jun 10, 2024
702d8c0
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 11, 2024
90e9e63
Set Version: 0.1.307
Jun 11, 2024
ca23db9
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 11, 2024
4941ea1
Set Version: 0.1.308
Jun 11, 2024
be0c2a3
removing unused variable
PetarMax Jun 11, 2024
a736864
renaming re-assigned variable
PetarMax Jun 11, 2024
7e71976
Make `_create_cse_accounts` apply recursively on `contract` field acc…
palinatolmach Jun 11, 2024
b1509f7
Code quality improvement
palinatolmach Jun 11, 2024
a085c81
Set Version: 0.1.309
Jun 11, 2024
c5c452c
Avoid adding new accs for constructors, add new CSE test for recursiv…
palinatolmach Jun 11, 2024
3c0b3ce
Enforce same symbolic storage variable name between constructor and f…
palinatolmach Jun 11, 2024
a46b3ec
tests with immutables
PetarMax Jun 11, 2024
69132aa
stabilising tests
PetarMax Jun 11, 2024
b2ae1fa
Merge branch 'master' into cse-contract-fields
PetarMax Jun 11, 2024
df4e23c
Set Version: 0.1.309
Jun 11, 2024
610d6e9
Update expected output, remove `Accounts` test
palinatolmach Jun 12, 2024
112a3fb
Update `contracts.k` expected output to reflect removal of `Accounts`
palinatolmach Jun 12, 2024
177c75e
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 12, 2024
a630375
Set Version: 0.1.310
Jun 12, 2024
b3e9746
Use default symbolic storage var name for constructor storage with CSE
palinatolmach Jun 12, 2024
86d5bf2
Documented `_create_cse_accounts`
palinatolmach Jun 12, 2024
ef0acc3
One other output update
palinatolmach Jun 12, 2024
01c4d7a
Merge branch 'master' into cse-contract-fields
palinatolmach Jun 12, 2024
c8ad934
Set Version: 0.1.311
Jun 12, 2024
78f2894
Apply refactoring from review comments
palinatolmach Jun 12, 2024
16cd4e5
Apply refactoring from review comments, preserve `new_init_cterm`
palinatolmach Jun 12, 2024
78d538d
Add test for recursive storage generation in new accounts
palinatolmach Jun 12, 2024
e82ab0c
Update output to account for TGovernance
palinatolmach Jun 12, 2024
40e0f37
correction
PetarMax Jun 12, 2024
4a89a45
Merge branch 'master' into cse-contract-fields
rv-jenkins Jun 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.301
0.1.302
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "kontrol"
version = "0.1.301"
version = "0.1.302"
description = "Foundry integration for KEVM"
authors = [
"Runtime Verification, Inc. <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion src/kontrol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
if TYPE_CHECKING:
from typing import Final

VERSION: Final = '0.1.301'
VERSION: Final = '0.1.302'
94 changes: 89 additions & 5 deletions src/kontrol/prove.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

from .deployment import DeploymentStateEntry
from .options import ProveOptions
from .solc_to_k import StorageField

_LOGGER: Final = logging.getLogger(__name__)

Expand Down Expand Up @@ -506,6 +507,7 @@ def _method_to_initialized_cfg(

empty_config = foundry.kevm.definition.empty_config(GENERATED_TOP_CELL)
kcfg, new_node_ids, init_node_id, target_node_id = _method_to_cfg(
foundry,
empty_config,
test.contract,
test.method,
Expand Down Expand Up @@ -541,6 +543,7 @@ def _method_to_initialized_cfg(


def _method_to_cfg(
foundry: Foundry,
empty_config: KInner,
contract: Contract,
method: Contract.Method | Contract.Constructor,
Expand All @@ -567,9 +570,11 @@ def _method_to_cfg(
program = contract_code

init_cterm = _init_cterm(
foundry,
empty_config,
program=program,
contract_code=bytesToken(contract_code),
storage_fields=contract.fields,
use_gas=use_gas,
deployment_state_entries=deployment_state_entries,
calldata=calldata,
Expand Down Expand Up @@ -759,9 +764,11 @@ def _init_account(address: int) -> None:


def _init_cterm(
foundry: Foundry,
empty_config: KInner,
program: bytes,
contract_code: KInner,
storage_fields: tuple[StorageField, ...],
use_gas: bool,
config_type: ConfigType,
active_symbolik: bool,
Expand Down Expand Up @@ -813,6 +820,8 @@ def _init_cterm(
'TRACEDATA_CELL': KApply('.List'),
}

storage_constraints = []

if config_type == ConfigType.TEST_CONFIG or active_symbolik:
init_account_list = _create_initial_account_list(contract_code, deployment_state_entries)
init_subst_test = {
Expand All @@ -832,11 +841,21 @@ def _init_cterm(
else:
# Symbolic accounts of all relevant contracts
# Status: Currently, only the executing contract
# TODO: Add all other accounts belonging to relevant contracts
accounts: list[KInner] = [
Foundry.symbolic_account(Foundry.symbolic_contract_prefix(), contract_code),
KVariable('ACCOUNTS_REST', sort=KSort('AccountCellMap')),
]
# TODO: Add all other accounts belonging to relevant contracts``
accounts: list[KInner] = []

# TODO(palina): executed contract's storage
storage_map = KVariable(Foundry.symbolic_contract_prefix() + '_STORAGE', sort=KSort('Map'))
# TODO(palina): executed contract's name
contract_name = Foundry.symbolic_contract_prefix() + '_ID'
new_accounts, storage_constraints, storage_map = _create_cse_accounts(
foundry, storage_fields, contract_name, storage_map
)

accounts.extend(new_accounts)

accounts.append(Foundry.symbolic_account(Foundry.symbolic_contract_prefix(), program, storage_map))
accounts.append(KVariable('ACCOUNTS_REST', sort=KSort('AccountCellMap')))

init_subst_accounts = {'ACCOUNTS_CELL': KEVM.accounts(accounts)}
init_subst.update(init_subst_accounts)
Expand Down Expand Up @@ -865,6 +884,10 @@ def _init_cterm(
mlEqualsFalse(KApply('_==Int_', [KVariable(contract_id, sort=KSort('Int')), Foundry.address_CHEATCODE()]))
)

# TODO(palina): make sure these constraints are getting applied
for constraint in storage_constraints:
init_cterm.add_constraint(constraint)

# The calling contract is assumed to be in the present accounts for non-tests
if not (config_type == ConfigType.TEST_CONFIG or active_symbolik):
init_cterm.add_constraint(
Expand Down Expand Up @@ -902,6 +925,67 @@ def _create_initial_account_list(
return init_account_list


def _create_cse_accounts(
foundry: Foundry, storage_fields: tuple[StorageField, ...], contract_name: str, contract_storage: KApply
) -> tuple[list[KApply], list[KApply], KApply]:
# TODO: call this function recursively
new_accounts = []
new_account_constraints = []

for field in storage_fields:
if field.data_type.startswith('contract '):
contract_type = field.data_type.split(' ')[1]
for contract_name, contract_obj in foundry.contracts.items():
if contract_name.split('%')[-1] == contract_type:
contract_code = KEVM.bin_runtime(KApply(f'contract_{contract_obj.name_with_path}'))
palinatolmach marked this conversation as resolved.
Show resolved Hide resolved
contract_account_name = 'CONTRACT-' + field.label.upper()
new_account = Foundry.symbolic_account(contract_account_name, contract_code)
new_accounts.append(new_account)

# TODO: handle the case where the field has a non-zero offset
# maxUInt160 &Int #lookup ( CONTRACT_STORAGE:Map , 0 )
contract_storage_lookup = KApply(
'_&Int_',
[
intToken(1461501637330902918203684832716283019655932542975),
KEVM.lookup(contract_storage, intToken(field.slot)),
],
)
new_account_constraints.append(
mlEqualsTrue(
KApply('_==Int_', [contract_storage_lookup, KVariable(contract_account_name + '_ID')])
)
)

# New contract account is not the cheatcode contract
new_account_constraints.append(
mlEqualsFalse(
KApply(
'_==Int_',
[
KVariable(contract_account_name + '_ID', sort=KSort('Int')),
Foundry.address_CHEATCODE(),
],
)
)
)

# New contract account is also not the symbolic contract account being executed
new_account_constraints.append(
mlEqualsFalse(
KApply(
'_==Int_',
[
KVariable(contract_account_name + '_ID', sort=KSort('Int')),
KVariable(Foundry.symbolic_contract_prefix(), sort=KSort('Int')),
],
)
)
)

return new_accounts, new_account_constraints, contract_storage


def _final_cterm(
empty_config: KInner,
program: KInner,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.13;

contract Token {
uint256 public totalSupply;

constructor(uint256 _totalSupply) {
totalSupply = _totalSupply;
}
}

contract Escrow {
Token token;
uint256 tokenTotalSupply;

function getTokenTotalSupply() public {
uint256 tokenTS = token.totalSupply();
tokenTotalSupply = tokenTS + 15;
}
}

contract ContractFieldTest {
Escrow escrow;

function setUp() public {
escrow = new Escrow();
}

/* Calling `getTokenTotalSupply` will summarize `totalSupply` and
include `Token token` into the list of accounts in `getTokenTotalSupply`'s summary
*/
function getEscrowToken() public {
escrow.getTokenTotalSupply();
}
}
Loading