Skip to content

Commit ce110e0

Browse files
committed
refactor init and final terms for symbolic exploration
1 parent 7f8ee84 commit ce110e0

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

src/kontrol/kdist/cheatcodes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,8 @@ Will also return true if REASON is `.Bytes`.
11611161
<id> CL </id>
11621162
<origin> OG </origin>
11631163
<prank>
1164-
<prevCaller> .Account => CL </prevCaller>
1165-
<prevOrigin> .Account => OG </prevOrigin>
1164+
<prevCaller> _ => CL </prevCaller>
1165+
<prevOrigin> _ => OG </prevOrigin>
11661166
<newCaller> _ => NEWCALLER </newCaller>
11671167
<newOrigin> _ => NEWORIGIN </newOrigin>
11681168
<active> false => true </active>

src/kontrol/prove.py

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,17 @@ def _method_to_cfg(
356356
program = KEVM.bin_runtime(KApply(f'contract_{contract.name_with_path}'))
357357
use_init_code = False
358358

359+
is_test = method.signature.startswith('test')
360+
failing = method.signature.startswith('testFail')
361+
359362
init_cterm = _init_cterm(
360363
empty_config,
361364
contract.name_with_path,
362365
program=program,
363366
calldata=calldata,
364367
callvalue=callvalue,
365368
use_gas=use_gas,
369+
is_test=is_test,
366370
)
367371
new_node_ids = []
368372

@@ -410,8 +414,6 @@ def _method_to_cfg(
410414
new_node_ids = [init_node.id]
411415
init_node_id = init_node.id
412416

413-
is_test = method.signature.startswith('test')
414-
failing = method.signature.startswith('testFail')
415417
final_cterm = _final_cterm(
416418
empty_config, contract.name_with_path, failing=failing, is_test=is_test, use_init_code=use_init_code
417419
)
@@ -425,6 +427,7 @@ def _init_cterm(
425427
contract_name: str,
426428
program: KInner,
427429
use_gas: bool,
430+
is_test: bool,
428431
*,
429432
setup_cterm: CTerm | None = None,
430433
calldata: KInner | None = None,
@@ -438,10 +441,11 @@ def _init_cterm(
438441
KApply('.Map'),
439442
intToken(1),
440443
)
444+
schedule = KApply('SHANGHAI_EVM')
441445
init_subst = {
442446
'MODE_CELL': KApply('NORMAL'),
443447
'USEGAS_CELL': TRUE if use_gas else FALSE,
444-
'SCHEDULE_CELL': KApply('SHANGHAI_EVM'),
448+
'SCHEDULE_CELL': schedule,
445449
'STATUSCODE_CELL': KVariable('STATUSCODE'),
446450
'CALLSTACK_CELL': KApply('.List'),
447451
'CALLDEPTH_CELL': intToken(0),
@@ -451,14 +455,11 @@ def _init_cterm(
451455
'LOG_CELL': KApply('.List'),
452456
'ID_CELL': Foundry.address_TEST_CONTRACT(),
453457
'CALLER_CELL': KVariable('CALLER_ID'),
458+
'TOUCHEDACCOUNTS_CELL': KApply('.Set'),
454459
'ACCESSEDACCOUNTS_CELL': KApply('.Set'),
455460
'ACCESSEDSTORAGE_CELL': KApply('.Map'),
456461
'INTERIMSTATES_CELL': KApply('.List'),
457462
'LOCALMEM_CELL': KApply('.Bytes_BYTES-HOOKED_Bytes'),
458-
'PREVCALLER_CELL': KApply('.Account_EVM-TYPES_Account'),
459-
'PREVORIGIN_CELL': KApply('.Account_EVM-TYPES_Account'),
460-
'NEWCALLER_CELL': KApply('.Account_EVM-TYPES_Account'),
461-
'NEWORIGIN_CELL': KApply('.Account_EVM-TYPES_Account'),
462463
'ACTIVE_CELL': FALSE,
463464
'STATIC_CELL': FALSE,
464465
'MEMORYUSED_CELL': intToken(0),
@@ -472,14 +473,8 @@ def _init_cterm(
472473
Foundry.account_CHEATCODE_ADDRESS(KApply('.Map')),
473474
]
474475
),
475-
'SINGLECALL_CELL': FALSE,
476476
'ISREVERTEXPECTED_CELL': FALSE,
477477
'ISOPCODEEXPECTED_CELL': FALSE,
478-
'EXPECTEDADDRESS_CELL': KApply('.Account_EVM-TYPES_Account'),
479-
'EXPECTEDVALUE_CELL': intToken(0),
480-
'EXPECTEDDATA_CELL': KApply('.Bytes_BYTES-HOOKED_Bytes'),
481-
'OPCODETYPE_CELL': KApply('.OpcodeType_FOUNDRY-CHEAT-CODES_OpcodeType'),
482-
'RECORDEVENT_CELL': FALSE,
483478
'ISEVENTEXPECTED_CELL': FALSE,
484479
'ISCALLWHITELISTACTIVE_CELL': FALSE,
485480
'ISSTORAGEWHITELISTACTIVE_CELL': FALSE,
@@ -500,6 +495,43 @@ def _init_cterm(
500495
init_subst['CALLGAS_CELL'] = intToken(0)
501496
init_subst['REFUND_CELL'] = intToken(0)
502497

498+
if not is_test:
499+
contract = KEVM.account_cell(
500+
KVariable('CONTRACT_ID'),
501+
KVariable('CONTRACT_BAL'),
502+
program,
503+
KVariable('CONTRACT_STORAGE'),
504+
KVariable('CONTRACT_STORAGE'),
505+
KVariable('CONTRACT_NONCE'),
506+
)
507+
init_subst.update(
508+
{
509+
'CALLSTACK_CELL': KVariable('CALLSTACK'),
510+
'CALLDEPTH_CELL': KVariable('CALLDEPTH'),
511+
'LOG_CELL': KVariable('LOGS'),
512+
'ID_CELL': KVariable('CONTRACT_ID'),
513+
'ACCOUNTS_CELL': KEVM.accounts(
514+
[
515+
contract,
516+
Foundry.account_CHEATCODE_ADDRESS(KApply('.Map')),
517+
]
518+
),
519+
}
520+
)
521+
del init_subst['CALLSTACK_CELL']
522+
del init_subst['LOG_CELL']
523+
del init_subst['INTERIMSTATES_CELL']
524+
525+
constraints = [
526+
mlEqualsTrue(KEVM.range_uint(256, KVariable('CONTRACT_BAL'))),
527+
mlEqualsTrue(KApply('#rangeNonce(_)_WORD_Bool_Int', KVariable('CONTRACT_NONCE'))),
528+
mlEqualsTrue(
529+
notBool(
530+
KApply('#isPrecompiledAccount(_,_)_EVM_Bool_Int_Schedule', [KVariable('CONTRACT_ID'), schedule])
531+
)
532+
),
533+
]
534+
503535
init_term = Subst(init_subst)(empty_config)
504536
init_cterm = CTerm.from_kast(init_term)
505537
init_cterm = KEVM.add_invariant(init_cterm)
@@ -514,7 +546,7 @@ def _init_cterm(
514546
def _final_cterm(
515547
empty_config: KInner, contract_name: str, *, failing: bool, is_test: bool = True, use_init_code: bool = False
516548
) -> CTerm:
517-
final_term = _final_term(empty_config, contract_name, use_init_code=use_init_code)
549+
final_term = _final_term(empty_config, contract_name, is_test, use_init_code=use_init_code)
518550
dst_failed_post = KEVM.lookup(KVariable('CHEATCODE_STORAGE_FINAL'), Foundry.loc_FOUNDRY_FAILED())
519551
foundry_success = Foundry.success(
520552
KVariable('STATUSCODE_FINAL'),
@@ -533,7 +565,7 @@ def _final_cterm(
533565
return final_cterm
534566

535567

536-
def _final_term(empty_config: KInner, contract_name: str, use_init_code: bool = False) -> KInner:
568+
def _final_term(empty_config: KInner, contract_name: str, is_test: bool, use_init_code: bool = False) -> KInner:
537569
program = (
538570
KEVM.init_bytecode(KApply(f'contract_{contract_name}'))
539571
if use_init_code
@@ -567,6 +599,27 @@ def _final_term(empty_config: KInner, contract_name: str, use_init_code: bool =
567599
'ADDRESSSET_CELL': KVariable('ADDRESSSET_FINAL'),
568600
'STORAGESLOTSET_CELL': KVariable('STORAGESLOTSET_FINAL'),
569601
}
602+
if not is_test:
603+
contract = KEVM.account_cell(
604+
KVariable('CONTRACT_ID'),
605+
KVariable('CONTRACT_BAL_FINAL'),
606+
program,
607+
KVariable('CONTRACT_STORAGE_FINAL'),
608+
KVariable('CONTRACT_ORIG_STORAGE_FINAL'),
609+
KVariable('CONTRACT_NONCE_FINAL'),
610+
)
611+
final_subst.update(
612+
{
613+
'ID_CELL': KVariable('CONTRACT_ID'),
614+
'ACCOUNTS_CELL': KEVM.accounts(
615+
[
616+
contract, # test contract address
617+
Foundry.account_CHEATCODE_ADDRESS(KApply('.Map')),
618+
KVariable('ACCOUNTS_FINAL'),
619+
]
620+
),
621+
}
622+
)
570623
return abstract_cell_vars(
571624
Subst(final_subst)(empty_config),
572625
[

0 commit comments

Comments
 (0)