diff --git a/blockchain-tests-skip.yml b/blockchain-tests-skip.yml index 567fcaa8d..98a8da812 100644 --- a/blockchain-tests-skip.yml +++ b/blockchain-tests-skip.yml @@ -6,59 +6,68 @@ filename: # List of specific tests names to be skipped with folder testname: vmArithmeticTest: - - expPower256Of256_d0g0v0_Shanghai - - exp_d9g0v0_Shanghai + - expPower256Of256_d0g0v0_Shanghai #RunResources error + - exp_d9g0v0_Shanghai #RunResources error vmPerformance: - - loopExp_d10g0v0_Shanghai - - loopExp_d11g0v0_Shanghai - - loopExp_d14g0v0_Shanghai - - loopExp_d9g0v0_Shanghai - - loopMul_d0g0v0_Shanghai - - loopMul_d1g0v0_Shanghai - - loopMul_d2g0v0_Shanghai - - performanceTester_d1g0v0_Shanghai - - performanceTester_d4g0v0_Shanghai + - loopExp_d10g0v0_Shanghai #RunResources error + - loopExp_d11g0v0_Shanghai #RunResources error + - loopExp_d12g0v0_Shanghai #RunResources error + - loopExp_d13g0v0_Shanghai #RunResources error + - loopExp_d14g0v0_Shanghai #RunResources error + - loopExp_d8g0v0_Shanghai #RunResources error + - loopExp_d9g0v0_Shanghai #RunResources error + - loopMul_d0g0v0_Shanghai #RunResources error + - loopMul_d1g0v0_Shanghai #RunResources error + - loopMul_d2g0v0_Shanghai #RunResources error + - performanceTester_d1g0v0_Shanghai #RunResources error + - performanceTester_d4g0v0_Shanghai #RunResources error vmTests: - - sha3_d3g0v0_Shanghai + - sha3_d3g0v0_Shanghai #RunResources error stAttackTest: - - ContractCreationSpam_d0g0v0_Shanghai + - ContractCreationSpam_d0g0v0_Shanghai #RunResources error stChainId: - chainId_d0g0v0_Shanghai stCreate2: + - RevertInCreateInInitCreate2_d0g0v0_Shanghai - create2callPrecompiles_d6g0v0_Shanghai - create2callPrecompiles_d7g0v0_Shanghai - create2collisionStorage_d0g0v0_Shanghai - create2collisionStorage_d1g0v0_Shanghai - create2collisionStorage_d2g0v0_Shanghai - stCallCreateCallCodeTest: - - Call1024PreCalls_d0g0v0_Shanghai - - Call1024PreCalls_d0g1v0_Shanghai - - CallRecursiveBombPreCall_d0g0v0_Shanghai stCreateTest: - - CreateOOGafterMaxCodesize_d2g0v0_Shanghai - - CreateOOGafterMaxCodesize_d3g0v0_Shanghai - - CreateOOGafterMaxCodesize_d5g0v0_Shanghai + - CreateOOGafterMaxCodesize_d2g0v0_Shanghai #RunResources error + - CreateOOGafterMaxCodesize_d3g0v0_Shanghai #RunResources error + - CreateOOGafterMaxCodesize_d5g0v0_Shanghai #RunResources error - CreateTransactionHighNonce_d0g0v0_Shanghai - CreateTransactionHighNonce_d0g0v1_Shanghai + stCallCreateCallCodeTest: + - Call1024PreCalls_d0g0v0_Shanghai #RunResources error + - Call1024PreCalls_d0g1v0_Shanghai #RunResources error stDelegatecallTestHomestead: - - Call1024PreCalls_d0g1v0_Shanghai - - Call1024PreCalls_d0g2v0_Shanghai - - CallRecursiveBombPreCall_d0g0v0_Shanghai - - Delegatecall1024_d0g0v0_Shanghai + - Call1024PreCalls_d0g1v0_Shanghai #RunResources error + - Call1024PreCalls_d0g2v0_Shanghai #RunResources error stEIP150singleCodeGasPrices: - - gasCostExp_d7g0v0_Shanghai + - gasCostExp_d7g0v0_Shanghai #RunResources error stExtCodeHash: - dynamicAccountOverwriteEmpty_d0g0v0_Shanghai stPreCompiledContracts2: - - CALLBlake2f_d9g0v0_Shanghai - - CALLCODEBlake2f_d9g0v0_Shanghai + - CALLBlake2f_d9g0v0_Shanghai #RunResources error + - CALLBlake2f_d9g1v0_Shanghai #RunResources error + - CALLBlake2f_d9g2v0_Shanghai #RunResources error + - CALLBlake2f_d9g3v0_Shanghai #RunResources error + - CALLCODEBlake2f_d9g0v0_Shanghai #RunResources error + - CALLCODEBlake2f_d9g1v0_Shanghai #RunResources error + - CALLCODEBlake2f_d9g2v0_Shanghai #RunResources error + - CALLCODEBlake2f_d9g3v0_Shanghai #RunResources error + - CALLCODEEcrecover0_Gas2999_d0g0v0_Shanghai - CALLCODEEcrecover0_NoGas_d0g0v0_Shanghai - CALLCODEEcrecover80_d0g0v0_Shanghai - CALLCODEEcrecoverR_prefixed0_d0g0v0_Shanghai - CALLCODERipemd160_0_d0g0v0_Shanghai - CALLCODERipemd160_4_gas719_d0g0v0_Shanghai - - CALLCODERipemd160_5_d0g0v0_Shanghai + - CALLCODERipemd160_5_d0g0v0_Shanghai #RunResources error - CALLCODESha256_5_d0g0v0_Shanghai + - CallEcrecover0_Gas2999_d0g0v0_Shanghai - CallEcrecover0_NoGas_d0g0v0_Shanghai - CallEcrecover80_d0g0v0_Shanghai - CallEcrecoverR_prefixed0_d0g0v0_Shanghai @@ -67,12 +76,18 @@ testname: - CallEcrecover_Overflow_d1g0v0_Shanghai - CallEcrecover_Overflow_d2g0v0_Shanghai - CallEcrecover_Overflow_d4g0v0_Shanghai + - CallEcrecover_Overflow_d5g0v0_Shanghai - CallRipemd160_0_d0g0v0_Shanghai - CallRipemd160_4_gas719_d0g0v0_Shanghai - - CallRipemd160_5_d0g0v0_Shanghai + - CallRipemd160_5_d0g0v0_Shanghai #RunResources error - CallSha256_5_d0g0v0_Shanghai - ecrecoverShortBuff_d0g0v0_Shanghai + - modexpRandomInput_d1g0v0_Shanghai + - modexpRandomInput_d1g1v0_Shanghai + - modexpRandomInput_d2g0v0_Shanghai + - modexpRandomInput_d2g1v0_Shanghai stPreCompiledContracts: + - idPrecomps_d4g0v0_Shanghai - modexp_d11g0v0_Shanghai - modexp_d11g1v0_Shanghai - modexp_d11g2v0_Shanghai @@ -101,10 +116,18 @@ testname: - modexp_d27g1v0_Shanghai - modexp_d27g2v0_Shanghai - modexp_d27g3v0_Shanghai + - modexp_d28g0v0_Shanghai + - modexp_d28g1v0_Shanghai + - modexp_d28g2v0_Shanghai + - modexp_d28g3v0_Shanghai - modexp_d29g0v0_Shanghai - modexp_d29g1v0_Shanghai - modexp_d29g2v0_Shanghai - modexp_d29g3v0_Shanghai + - modexp_d2g0v0_Shanghai + - modexp_d2g1v0_Shanghai + - modexp_d2g2v0_Shanghai + - modexp_d2g3v0_Shanghai - modexp_d30g0v0_Shanghai - modexp_d30g1v0_Shanghai - modexp_d30g2v0_Shanghai @@ -113,87 +136,176 @@ testname: - modexp_d33g1v0_Shanghai - modexp_d33g2v0_Shanghai - modexp_d33g3v0_Shanghai + - modexp_d36g0v0_Shanghai + - modexp_d36g1v0_Shanghai + - modexp_d36g2v0_Shanghai + - modexp_d36g3v0_Shanghai + - modexp_d37g0v0_Shanghai + - modexp_d37g1v0_Shanghai + - modexp_d37g2v0_Shanghai + - modexp_d37g3v0_Shanghai + - precompsEIP2929_d10g0v0_Shanghai + - precompsEIP2929_d113g0v0_Shanghai + - precompsEIP2929_d114g0v0_Shanghai + - precompsEIP2929_d115g0v0_Shanghai + - precompsEIP2929_d131g0v0_Shanghai + - precompsEIP2929_d132g0v0_Shanghai + - precompsEIP2929_d133g0v0_Shanghai + - precompsEIP2929_d149g0v0_Shanghai + - precompsEIP2929_d150g0v0_Shanghai + - precompsEIP2929_d167g0v0_Shanghai + - precompsEIP2929_d168g0v0_Shanghai + - precompsEIP2929_d185g0v0_Shanghai + - precompsEIP2929_d186g0v0_Shanghai + - precompsEIP2929_d187g0v0_Shanghai + - precompsEIP2929_d203g0v0_Shanghai + - precompsEIP2929_d204g0v0_Shanghai + - precompsEIP2929_d205g0v0_Shanghai + - precompsEIP2929_d221g0v0_Shanghai + - precompsEIP2929_d222g0v0_Shanghai + - precompsEIP2929_d223g0v0_Shanghai + - precompsEIP2929_d239g0v0_Shanghai - precompsEIP2929_d23g0v0_Shanghai + - precompsEIP2929_d240g0v0_Shanghai - precompsEIP2929_d24g0v0_Shanghai + - precompsEIP2929_d257g0v0_Shanghai + - precompsEIP2929_d258g0v0_Shanghai + - precompsEIP2929_d259g0v0_Shanghai - precompsEIP2929_d25g0v0_Shanghai + - precompsEIP2929_d275g0v0_Shanghai + - precompsEIP2929_d276g0v0_Shanghai + - precompsEIP2929_d277g0v0_Shanghai + - precompsEIP2929_d293g0v0_Shanghai + - precompsEIP2929_d294g0v0_Shanghai + - precompsEIP2929_d311g0v0_Shanghai + - precompsEIP2929_d312g0v0_Shanghai + - precompsEIP2929_d313g0v0_Shanghai + - precompsEIP2929_d41g0v0_Shanghai + - precompsEIP2929_d42g0v0_Shanghai - precompsEIP2929_d59g0v0_Shanghai - precompsEIP2929_d60g0v0_Shanghai + - precompsEIP2929_d77g0v0_Shanghai + - precompsEIP2929_d78g0v0_Shanghai + - precompsEIP2929_d79g0v0_Shanghai + - precompsEIP2929_d8g0v0_Shanghai - precompsEIP2929_d95g0v0_Shanghai - precompsEIP2929_d96g0v0_Shanghai - precompsEIP2929_d97g0v0_Shanghai + - precompsEIP2929_d9g0v0_Shanghai stRandom2: - - randomStatetest458_d0g0v0_Shanghai - - randomStatetest476_d0g0v0_Shanghai + - randomStatetest458_d0g0v0_Shanghai #RunResources error + - randomStatetest476_d0g0v0_Shanghai #RunResources error - randomStatetest487_d0g0v0_Shanghai - randomStatetest564_d0g0v0_Shanghai + - randomStatetest571_d0g0v0_Shanghai - randomStatetest605_d0g0v0_Shanghai - randomStatetest650_d0g0v0_Shanghai stQuadraticComplexityTest: - - Call1MB1024Calldepth_d0g1v0_Shanghai - - Call20KbytesContract50_1_d0g1v0_Shanghai - - Call20KbytesContract50_2_d0g1v0_Shanghai - - Call20KbytesContract50_3_d0g1v0_Shanghai - - Return50000_2_d0g1v0_Shanghai - - Return50000_d0g1v0_Shanghai + - Call1MB1024Calldepth_d0g1v0_Shanghai #RunResources error + - Call20KbytesContract50_1_d0g1v0_Shanghai #RunResources error + - Call20KbytesContract50_2_d0g1v0_Shanghai #RunResources error + - Call20KbytesContract50_3_d0g0v0_Shanghai #RunResources error + - Call20KbytesContract50_3_d0g1v0_Shanghai #RunResources error + - Call50000_d0g1v0_Shanghai #RunResources error + - Call50000_ecrec_d0g1v0_Shanghai #RunResources error + - Call50000_identity2_d0g1v0_Shanghai #RunResources error + - Call50000_identity_d0g1v0_Shanghai #RunResources error + - Call50000_rip160_d0g0v0_Shanghai #RunResources error + - Call50000_rip160_d0g1v0_Shanghai #RunResources error + - Call50000_sha256_d0g0v0_Shanghai + - Call50000_sha256_d0g1v0_Shanghai + - Callcode50000_d0g1v0_Shanghai #RunResources error + - Return50000_2_d0g0v0_Shanghai #RunResources error + - Return50000_2_d0g1v0_Shanghai #RunResources error + - Return50000_d0g0v0_Shanghai #RunResources error + - Return50000_d0g1v0_Shanghai #RunResources error stRandom: - randomStatetest116_d0g0v0_Shanghai - - randomStatetest159_d0g0v0_Shanghai - - randomStatetest163_d0g0v0_Shanghai - - randomStatetest185_d0g0v0_Shanghai - - randomStatetest189_d0g0v0_Shanghai + - randomStatetest159_d0g0v0_Shanghai #RunResources error + - randomStatetest163_d0g0v0_Shanghai #RunResources error + - randomStatetest177_d0g0v0_Shanghai #RunResources error + - randomStatetest185_d0g0v0_Shanghai #RunResources error - randomStatetest242_d0g0v0_Shanghai - - randomStatetest326_d0g0v0_Shanghai - - randomStatetest354_d0g0v0_Shanghai - - randomStatetest367_d0g0v0_Shanghai - - randomStatetest36_d0g0v0_Shanghai + - randomStatetest320_d0g0v0_Shanghai #RunResources error + - randomStatetest326_d0g0v0_Shanghai #RunResources error + - randomStatetest354_d0g0v0_Shanghai #RunResources error + - randomStatetest367_d0g0v0_Shanghai #RunResources error + - randomStatetest36_d0g0v0_Shanghai #RunResources error - randomStatetest382_d0g0v0_Shanghai - - randomStatetest384_d0g0v0_Shanghai - - randomStatetest43_d0g0v0_Shanghai - - randomStatetest48_d0g0v0_Shanghai + - randomStatetest384_d0g0v0_Shanghai #RunResources error + - randomStatetest43_d0g0v0_Shanghai #RunResources error + - randomStatetest48_d0g0v0_Shanghai #RunResources error - randomStatetest64_d0g0v0_Shanghai - randomStatetest85_d0g0v0_Shanghai + stRevertTest: + - RevertInCreateInInit_d0g0v0_Shanghai + - RevertPrecompiledTouchExactOOG_d13g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d13g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d14g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d14g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d15g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d21g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d21g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d22g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d22g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d23g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d29g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d29g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d30g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d30g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d31g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d5g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d5g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d6g1v0_Shanghai + - RevertPrecompiledTouchExactOOG_d6g2v0_Shanghai + - RevertPrecompiledTouchExactOOG_d7g1v0_Shanghai stSStoreTest: + - InitCollision_d0g0v0_Shanghai - InitCollision_d1g0v0_Shanghai + - InitCollision_d2g0v0_Shanghai - InitCollision_d3g0v0_Shanghai stReturnDataTest: - modexp_modsize0_returndatasize_d4g0v0_Shanghai stStaticCall: - - static_Call1MB1024Calldepth_d1g0v0_Shanghai - StaticcallToPrecompileFromCalledContract_d0g0v0_Shanghai - StaticcallToPrecompileFromContractInitialization_d0g0v0_Shanghai - StaticcallToPrecompileFromTransaction_d0g0v0_Shanghai - - static_Call50000_d0g0v0_Shanghai - - static_Call50000_d1g0v0_Shanghai - - static_Call50000_ecrec_d0g0v0_Shanghai - - static_Call50000_ecrec_d1g0v0_Shanghai - - static_Call50000_identity2_d0g0v0_Shanghai - - static_Call50000_identity2_d1g0v0_Shanghai - - static_Call50000_identity_d0g0v0_Shanghai - - static_Call50000_identity_d1g0v0_Shanghai - - static_Call50000_rip160_d0g0v0_Shanghai - - static_Call50000_rip160_d1g0v0_Shanghai - - static_Call50000bytesContract50_1_d0g0v0_Shanghai - - static_Call50000bytesContract50_1_d1g0v0_Shanghai - - static_Call50000bytesContract50_2_d0g0v0_Shanghai - - static_Call50000bytesContract50_2_d1g0v0_Shanghai - - static_Call50000bytesContract50_3_d0g0v0_Shanghai - - static_Call50000bytesContract50_3_d1g0v0_Shanghai + - static_Call1MB1024Calldepth_d1g0v0_Shanghai #RunResources error + - static_Call50000_d0g0v0_Shanghai #RunResources error + - static_Call50000_d1g0v0_Shanghai #RunResources error + - static_Call50000_ecrec_d0g0v0_Shanghai #RunResources error + - static_Call50000_ecrec_d1g0v0_Shanghai #RunResources error + - static_Call50000_identity2_d0g0v0_Shanghai #RunResources error + - static_Call50000_identity2_d1g0v0_Shanghai #RunResources error + - static_Call50000_identity_d0g0v0_Shanghai #RunResources error + - static_Call50000_identity_d1g0v0_Shanghai #RunResources error + - static_Call50000_rip160_d0g0v0_Shanghai #RunResources error + - static_Call50000_rip160_d1g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_1_d0g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_1_d1g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_2_d0g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_2_d1g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_3_d0g0v0_Shanghai #RunResources error + - static_Call50000bytesContract50_3_d1g0v0_Shanghai #RunResources error - static_CallEcrecover0_0input_d6g0v0_Shanghai - static_CallEcrecover0_0input_d7g0v0_Shanghai + - static_CallEcrecover0_Gas2999_d0g0v0_Shanghai + - static_CallEcrecover0_NoGas_d0g0v0_Shanghai - static_CallEcrecover80_d0g0v0_Shanghai - static_CallEcrecoverR_prefixed0_d0g0v0_Shanghai - static_CallRipemd160_4_gas719_d0g0v0_Shanghai - - static_CallRipemd160_5_d0g0v0_Shanghai + - static_CallRipemd160_5_d0g0v0_Shanghai #RunResources error - static_CallSha256_5_d0g0v0_Shanghai - - static_LoopCallsThenRevert_d0g0v0_Shanghai - - static_LoopCallsThenRevert_d0g1v0_Shanghai - - static_Return50000_2_d0g0v0_Shanghai + - static_LoopCallsThenRevert_d0g0v0_Shanghai #RunResources error + - static_LoopCallsThenRevert_d0g1v0_Shanghai #RunResources error + - static_Return50000_2_d0g0v0_Shanghai #RunResources error stSpecialTest: - - JUMPDEST_Attack_d0g0v0_Shanghai - - JUMPDEST_AttackwithJump_d0g0v0_Shanghai + - JUMPDEST_Attack_d0g0v0_Shanghai #RunResources error + - JUMPDEST_AttackwithJump_d0g0v0_Shanghai #RunResources error + - block504980_d0g0v0_Shanghai #RunResources error + - failed_tx_xcf416c53_d0g0v0_Shanghai #RunResources error stSystemOperationsTest: - CallToNameRegistratorNotMuchMemory0_d0g0v0_Shanghai - - CallToNameRegistratorNotMuchMemory1_d0g0v0_Shanghai - multiSelfdestruct_d0g0v0_Shanghai - multiSelfdestruct_d4g0v0_Shanghai stStaticFlagEnabled: @@ -207,7 +319,7 @@ testname: - DelegatecallToPrecompileFromContractInitialization_d0g0v0_Shanghai - DelegatecallToPrecompileFromTransaction_d0g0v0_Shanghai stTimeConsuming: - - CALLBlake2f_MaxRounds_d0g0v0_Shanghai + - CALLBlake2f_MaxRounds_d0g0v0_Shanghai #RunResources error - static_Call50000_sha256_d0g0v0_Shanghai - static_Call50000_sha256_d1g0v0_Shanghai stTransactionTest: @@ -220,11 +332,26 @@ testname: - ecpairing_empty_data_insufficient_gas_d0g2v0_Shanghai - ecpairing_one_point_fail_d0g0v0_Shanghai - ecpairing_one_point_with_g1_zero_d0g0v0_Shanghai + - ecpairing_one_point_with_g2_zero_d0g0v0_Shanghai + - ecpairing_one_point_with_g2_zero_d0g2v0_Shanghai + - ecpairing_one_point_with_g2_zero_d0g3v0_Shanghai - ecpairing_three_point_fail_1_d0g0v0_Shanghai + - ecpairing_three_point_match_1_d0g0v0_Shanghai + - ecpairing_three_point_match_1_d0g3v0_Shanghai - ecpairing_two_point_fail_1_d0g0v0_Shanghai - ecpairing_two_point_fail_2_d0g0v0_Shanghai - ecpairing_two_point_match_1_d0g0v0_Shanghai + - ecpairing_two_point_match_2_d0g0v0_Shanghai + - ecpairing_two_point_match_2_d0g3v0_Shanghai + - ecpairing_two_point_match_3_d0g0v0_Shanghai + - ecpairing_two_point_match_3_d0g3v0_Shanghai + - ecpairing_two_point_match_4_d0g0v0_Shanghai + - ecpairing_two_point_match_4_d0g3v0_Shanghai - ecpairing_two_point_match_5_d0g0v0_Shanghai + - ecpairing_two_point_oog_d0g0v0_Shanghai + - ecpairing_two_point_oog_d0g3v0_Shanghai + - ecpairing_two_points_with_one_g2_zero_d0g0v0_Shanghai + - ecpairing_two_points_with_one_g2_zero_d0g3v0_Shanghai - pairingTest_d0g0v0_Shanghai - pairingTest_d1g0v0_Shanghai - pairingTest_d2g0v0_Shanghai @@ -350,13 +477,13 @@ testname: # The first level corresponds to the directory, the second to the list of file names regex to ignore. regex: stMemoryStressTest: - - mload32bitBound_return.* - - CREATE_Bounds.* - - CREATE2_Bounds.* - - CALL_Bounds.* - - CALLCODE_Bounds.* - - DELEGATECALL_Bounds.* - - static_CALL_Bounds.* + - mload32bitBound_return.* # ef-tests #565 + - CREATE_Bounds.* # ef-tests #565 + - CREATE2_Bounds.* # ef-tests #565 + - CALL_Bounds.* # ef-tests #565 + - CALLCODE_Bounds.* # ef-tests #565 + - DELEGATECALL_Bounds.* # ef-tests #565 + - static_CALL_Bounds.* # ef-tests #565 stZeroKnowledge: - .*ecmul.* stZeroKnowledge2: diff --git a/src/kakarot/evm.cairo b/src/kakarot/evm.cairo index d1ce06dbd..b9acc4125 100644 --- a/src/kakarot/evm.cairo +++ b/src/kakarot/evm.cairo @@ -179,7 +179,7 @@ namespace EVM { program_counter=self.program_counter, stopped=TRUE, gas_left=0, - gas_refund=self.gas_refund, + gas_refund=0, reverted=Errors.EXCEPTIONAL_HALT, ); } diff --git a/src/kakarot/gas.cairo b/src/kakarot/gas.cairo index dbfa1f326..0cadaadce 100644 --- a/src/kakarot/gas.cairo +++ b/src/kakarot/gas.cairo @@ -1,9 +1,10 @@ from starkware.cairo.common.math import split_felt, unsigned_div_rem from starkware.cairo.common.math_cmp import is_le, is_not_zero, is_nn from starkware.cairo.common.bool import FALSE -from starkware.cairo.common.uint256 import Uint256, uint256_lt +from starkware.cairo.common.uint256 import Uint256, uint256_lt, uint256_eq from kakarot.model import model +from utils.utils import Helpers namespace Gas { const JUMPDEST = 1; @@ -102,7 +103,8 @@ namespace Gas { func memory_expansion_cost_saturated{range_check_ptr}( words_len: felt, offset: Uint256, size: Uint256 ) -> model.MemoryExpansion { - if (size.low == 0) { + let (is_zero) = uint256_eq(size, Uint256(low=0, high=0)); + if (is_zero != FALSE) { let expansion = model.MemoryExpansion(cost=0, new_words_len=words_len); return expansion; } @@ -134,6 +136,13 @@ namespace Gas { words_len: felt, offset_1: Uint256*, size_1: Uint256*, offset_2: Uint256*, size_2: Uint256* ) -> model.MemoryExpansion { alloc_locals; + let (is_zero_1) = uint256_eq([size_1], Uint256(0, 0)); + let (is_zero_2) = uint256_eq([size_2], Uint256(0, 0)); + let is_zero = is_zero_1 * is_zero_2; + if (is_zero != FALSE) { + let expansion = model.MemoryExpansion(cost=0, new_words_len=words_len); + return expansion; + } let max_expansion_is_2 = is_le(offset_1.low + size_1.low, offset_2.low + size_2.low); let max_expansion = max_expansion_is_2 * (offset_2.low + size_2.low) + ( 1 - max_expansion_is_2 diff --git a/src/kakarot/instructions/environmental_information.cairo b/src/kakarot/instructions/environmental_information.cairo index 131d92723..05398f5e4 100644 --- a/src/kakarot/instructions/environmental_information.cairo +++ b/src/kakarot/instructions/environmental_information.cairo @@ -9,7 +9,7 @@ from starkware.cairo.common.cairo_keccak.keccak import cairo_keccak_bigend, fina from starkware.cairo.common.memset import memset from starkware.cairo.common.math import unsigned_div_rem, split_felt from starkware.cairo.common.math_cmp import is_not_zero, is_le -from starkware.cairo.common.uint256 import Uint256, uint256_le, uint256_add +from starkware.cairo.common.uint256 import Uint256, uint256_le, uint256_add, uint256_eq from kakarot.account import Account from kakarot.evm import EVM @@ -152,7 +152,7 @@ namespace EnvironmentalInformation { return evm; } - func exec_copy{ + func exec_returndatacopy{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, @@ -163,13 +163,15 @@ namespace EnvironmentalInformation { }(evm: model.EVM*) -> model.EVM* { alloc_locals; + // STACK let (popped) = Stack.pop_n(3); - let dest_offset = popped[0]; - let offset = popped[1]; + let memory_offset = popped[0]; + let returndata_offset = popped[1]; let size = popped[2]; + // GAS let memory_expansion = Gas.memory_expansion_cost_saturated( - memory.words_len, dest_offset, size + memory.words_len, memory_offset, size ); // Any size upper than 2**128 will cause an OOG error, considering the maximum gas for a transaction. @@ -186,17 +188,18 @@ namespace EnvironmentalInformation { return evm; } - let opcode_number = [evm.message.bytecode + evm.program_counter]; + // OPERATION + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); // Offset.high != 0 means that the sliced data is surely 0x00...00 // And storing 0 in Memory is just doing nothing. - if (offset.high != 0) { - if (opcode_number != 0x3e) { - return evm; - } - + if (returndata_offset.high != 0) { // We still check for OOB returndatacopy - let (max_index, carry) = uint256_add(offset, size); + let (max_index, carry) = uint256_add(returndata_offset, size); let (high, low) = split_felt(evm.return_data_len); let (is_in_bounds) = uint256_le(max_index, Uint256(low=low, high=high)); let is_in_bounds = is_in_bounds * (1 - carry); @@ -208,9 +211,81 @@ namespace EnvironmentalInformation { return evm; } + let (sliced_data: felt*) = alloc(); + tempvar is_in_bounds = is_le(returndata_offset.low + size.low, evm.return_data_len); + if (is_in_bounds == FALSE) { + let (revert_reason_len, revert_reason) = Errors.outOfBoundsRead(); + let evm = EVM.stop(evm, revert_reason_len, revert_reason, Errors.EXCEPTIONAL_HALT); + return evm; + } + slice(sliced_data, evm.return_data_len, evm.return_data, returndata_offset.low, size.low); + + Memory.store_n(size.low, sliced_data, memory_offset.low); + + return evm; + } + + func exec_copy{ + syscall_ptr: felt*, + pedersen_ptr: HashBuiltin*, + range_check_ptr, + bitwise_ptr: BitwiseBuiltin*, + stack: model.Stack*, + memory: model.Memory*, + state: model.State*, + }(evm: model.EVM*) -> model.EVM* { + alloc_locals; + + // STACK + let (popped) = Stack.pop_n(3); + let dest_offset = popped[0]; + let offset = popped[1]; + let size = popped[2]; + + // if size == 0, we can optimize by returning early + // fixed opcode cost has already been charged as both + // calldatacopy and codecopy don't have additional checks + let (is_zero) = uint256_eq(size, Uint256(low=0, high=0)); + if (is_zero != FALSE) { + return evm; + } + + // GAS + let memory_expansion = Gas.memory_expansion_cost_saturated( + memory.words_len, dest_offset, size + ); + + // Any size upper than 2**128 will cause an OOG error, considering the maximum gas for a transaction. + let upper_bytes_bound = size.low + 31; + let (words, _) = unsigned_div_rem(upper_bytes_bound, 32); + let copy_gas_cost_low = words * Gas.COPY; + tempvar copy_gas_cost_high = is_not_zero(size.high) * 2 ** 128; + + // static cost handled in jump table + let evm = EVM.charge_gas( + evm, memory_expansion.cost + copy_gas_cost_low + copy_gas_cost_high + ); + if (evm.reverted != FALSE) { + return evm; + } + + // OPERATION + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); + + let opcode_number = [evm.message.bytecode + evm.program_counter]; + + // Offset.high != 0 means that the sliced data is surely 0x00...00 + // And storing 0 in Memory is just doing nothing. + if (offset.high != 0) { + return evm; + } + // 0x37: calldatacopy // 0x39: codecopy - // 0x3e: returndatacopy let (sliced_data: felt*) = alloc(); local data_len; local data: felt*; @@ -219,23 +294,9 @@ namespace EnvironmentalInformation { assert data = evm.message.calldata; tempvar range_check_ptr = range_check_ptr; } else { - if (opcode_number == 0x39) { - assert data_len = evm.message.bytecode_len; - assert data = evm.message.bytecode; - tempvar range_check_ptr = range_check_ptr; - } else { - tempvar is_in_bounds = is_le(offset.low + size.low, evm.return_data_len); - if (is_in_bounds == FALSE) { - let (revert_reason_len, revert_reason) = Errors.outOfBoundsRead(); - let evm = EVM.stop( - evm, revert_reason_len, revert_reason, Errors.EXCEPTIONAL_HALT - ); - return evm; - } - assert data_len = evm.return_data_len; - assert data = evm.return_data; - tempvar range_check_ptr = range_check_ptr; - } + assert data_len = evm.message.bytecode_len; + assert data = evm.message.bytecode; + tempvar range_check_ptr = range_check_ptr; } let range_check_ptr = [ap - 1]; slice(sliced_data, data_len, data, offset.low, size.low); @@ -346,6 +407,12 @@ namespace EnvironmentalInformation { return evm; } + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); + // Offset.high != 0 means that the sliced data is surely 0x00...00 // And storing 0 in Memory is just doing nothing if (offset.high != 0) { diff --git a/src/kakarot/instructions/logging_operations.cairo b/src/kakarot/instructions/logging_operations.cairo index b7031be79..559bb2a7d 100644 --- a/src/kakarot/instructions/logging_operations.cairo +++ b/src/kakarot/instructions/logging_operations.cairo @@ -62,6 +62,11 @@ namespace LoggingOperations { if (evm.reverted != FALSE) { return evm; } + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); let (data: felt*) = alloc(); Memory.load_n(size.low, data, offset.low); EVM.push_event(evm, topics_len, popped + 4, size.low, data); diff --git a/src/kakarot/instructions/memory_operations.cairo b/src/kakarot/instructions/memory_operations.cairo index ea7b470de..7922d2eaf 100644 --- a/src/kakarot/instructions/memory_operations.cairo +++ b/src/kakarot/instructions/memory_operations.cairo @@ -40,6 +40,12 @@ namespace MemoryOperations { return evm; } + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); + let value = Memory.load(offset.low); Stack.push_uint256(value); @@ -68,6 +74,11 @@ namespace MemoryOperations { if (evm.reverted != FALSE) { return evm; } + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); Memory.store(value, offset.low); return evm; @@ -208,6 +219,11 @@ namespace MemoryOperations { let (value_pointer: felt*) = alloc(); assert [value_pointer] = remainder.low; + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); Memory.store_n(1, value_pointer, offset.low); return evm; diff --git a/src/kakarot/instructions/sha3.cairo b/src/kakarot/instructions/sha3.cairo index d4b546356..6c0e21642 100644 --- a/src/kakarot/instructions/sha3.cairo +++ b/src/kakarot/instructions/sha3.cairo @@ -33,6 +33,7 @@ namespace Sha3 { let offset = popped[0]; let size = popped[1]; + // GAS let memory_expansion = Gas.memory_expansion_cost_saturated(memory.words_len, offset, size); let (words, _) = unsigned_div_rem(size.low + 31, 32); let words_gas_cost_low = Gas.KECCAK256_WORD * words; @@ -44,6 +45,13 @@ namespace Sha3 { return evm; } + // OPERATION + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + words_len=memory_expansion.new_words_len, + ); + let (bigendian_data: felt*) = alloc(); Memory.load_n(size.low, bigendian_data, offset.low); diff --git a/src/kakarot/instructions/system_operations.cairo b/src/kakarot/instructions/system_operations.cairo index 381932c18..9a6f6783a 100644 --- a/src/kakarot/instructions/system_operations.cairo +++ b/src/kakarot/instructions/system_operations.cairo @@ -74,9 +74,27 @@ namespace SystemOperations { } // Load bytecode + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + memory_expansion.new_words_len, + ); let (bytecode: felt*) = alloc(); Memory.load_n(size.low, bytecode, offset.low); + let (return_data) = alloc(); + + tempvar evm = new model.EVM( + message=evm.message, + return_data_len=0, + return_data=return_data, + program_counter=evm.program_counter, + stopped=evm.stopped, + gas_left=evm.gas_left, + gas_refund=evm.gas_refund, + reverted=evm.reverted, + ); + let target_address = CreateHelper.get_evm_address( evm.message.address.evm, popped_len, popped, size.low, bytecode ); @@ -109,10 +127,6 @@ namespace SystemOperations { let evm = EVM.charge_gas(evm, gas_limit); // Operation - tempvar memory = new model.Memory( - memory.word_dict_start, memory.word_dict, memory_expansion.new_words_len - ); - // Check target account availability let is_collision = Account.has_code_or_nonce(target_account); if (is_collision != 0) { @@ -240,6 +254,11 @@ namespace SystemOperations { return evm; } + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + memory_expansion.new_words_len, + ); let (local return_data: felt*) = alloc(); Memory.load_n(size.low, return_data, offset.low); @@ -279,6 +298,11 @@ namespace SystemOperations { // Load revert reason from offset let (return_data: felt*) = alloc(); + tempvar memory = new model.Memory( + word_dict_start=memory.word_dict_start, + word_dict=memory.word_dict, + memory_expansion.new_words_len, + ); Memory.load_n(size.low, return_data, offset.low); let evm = EVM.stop(evm, size.low, return_data, Errors.REVERT); diff --git a/src/kakarot/interpreter.cairo b/src/kakarot/interpreter.cairo index e376439bb..beefdab68 100644 --- a/src/kakarot/interpreter.cairo +++ b/src/kakarot/interpreter.cairo @@ -253,7 +253,7 @@ namespace Interpreter { jmp end; call EnvironmentalInformation.exec_returndatasize; // 0x3d jmp end; - call EnvironmentalInformation.exec_copy; // 0x3e + call EnvironmentalInformation.exec_returndatacopy; // 0x3e jmp end; call EnvironmentalInformation.exec_extcodehash; // 0x3f jmp end; @@ -700,6 +700,23 @@ namespace Interpreter { } if (evm.message.depth == 0) { + if (evm.reverted != 0) { + // All REVERTS in a root ctx set the gas_refund to 0. + // Only if the execution has halted exceptionnaly, consume all gas + let is_not_exceptional_revert = Helpers.is_zero(evm.reverted - 1); + let gas_left = is_not_exceptional_revert * evm.gas_left; + tempvar evm = new model.EVM( + message=evm.message, + return_data_len=evm.return_data_len, + return_data=evm.return_data, + program_counter=evm.program_counter, + stopped=evm.stopped, + gas_left=gas_left, + gas_refund=0, + reverted=evm.reverted, + ); + return evm; + } if (evm.message.is_create != FALSE) { let evm = Internals._finalize_create_tx(evm); return evm; @@ -783,15 +800,19 @@ namespace Interpreter { local code_address: felt; if (is_deploy_tx != FALSE) { let (empty: felt*) = alloc(); + let (init_code_words, _) = unsigned_div_rem(bytecode_len + 31, 32); + let init_code_gas = Gas.INIT_CODE_WORD_COST * init_code_words; assert bytecode = tmp_calldata; assert calldata = empty; - assert intrinsic_gas = tmp_intrinsic_gas + Gas.CREATE; + assert intrinsic_gas = tmp_intrinsic_gas + Gas.CREATE + init_code_gas; assert code_address = 0; + tempvar range_check_ptr = range_check_ptr; } else { assert bytecode = tmp_bytecode; assert calldata = tmp_calldata; assert intrinsic_gas = tmp_intrinsic_gas; assert code_address = address.evm; + tempvar range_check_ptr = range_check_ptr; } let (valid_jumpdests_start, valid_jumpdests) = Account.get_jumpdests( @@ -834,14 +855,14 @@ namespace Interpreter { let is_gas_limit_enough = is_le(intrinsic_gas, gas_limit); if (is_gas_limit_enough == FALSE) { let evm = EVM.halt_validation_failed(evm); - return (evm, stack, memory, state, gas_limit); + return (evm, stack, memory, state, 0); } // TODO: same as below let (is_value_le_balance) = uint256_le([value], [sender.balance]); if (is_value_le_balance == FALSE) { let evm = EVM.halt_validation_failed(evm); - return (evm, stack, memory, state, gas_limit); + return (evm, stack, memory, state, 0); } let (balance_post_value_transfer) = uint256_sub([sender.balance], [value]); @@ -853,7 +874,7 @@ namespace Interpreter { let (can_pay_gasfee) = uint256_le(fee_u256, balance_post_value_transfer); if (can_pay_gasfee == FALSE) { let evm = EVM.halt_validation_failed(evm); - return (evm, stack, memory, state, gas_limit); + return (evm, stack, memory, state, 0); } tempvar is_initcode_invalid = is_deploy_tx * is_le( @@ -861,7 +882,7 @@ namespace Interpreter { ); if (is_initcode_invalid != FALSE) { let evm = EVM.halt_validation_failed(evm); - return (evm, stack, memory, state, gas_limit); + return (evm, stack, memory, state, 0); } // Charge the gas fee to the user without setting up a transfer. @@ -956,18 +977,38 @@ namespace Internals { if (success == 0) { // Reverts and burn all gas - let evm = EVM.charge_gas(evm, evm.gas_left + 1); + let (revert_reason_len, revert_reason) = Errors.outOfGas( + evm.gas_left, code_deposit_cost + ); + tempvar evm = new model.EVM( + message=evm.message, + return_data_len=revert_reason_len, + return_data=revert_reason, + program_counter=evm.program_counter, + stopped=TRUE, + gas_left=0, + gas_refund=0, + reverted=Errors.EXCEPTIONAL_HALT, + ); return evm; } - let evm = EVM.charge_gas(evm, code_deposit_cost); - let account = State.get_account(evm.message.address.evm); let account = Account.set_code(account, evm.return_data_len, evm.return_data); State.update_account(account); State.finalize(); - let evm = EVM.update_return_data(evm, 2, cast(evm.message.address, felt*)); + // Update gas and return data - we know gas_left > code_deposit_cost + tempvar evm = new model.EVM( + message=evm.message, + return_data_len=2, + return_data=cast(evm.message.address, felt*), + program_counter=evm.program_counter, + stopped=evm.stopped, + gas_left=evm.gas_left - code_deposit_cost, + gas_refund=evm.gas_refund, + reverted=evm.reverted, + ); return evm; } diff --git a/src/kakarot/memory.cairo b/src/kakarot/memory.cairo index 8501b404a..80656fdc9 100644 --- a/src/kakarot/memory.cairo +++ b/src/kakarot/memory.cairo @@ -47,11 +47,6 @@ namespace Memory { func store{range_check_ptr, memory: model.Memory*}(element: Uint256, offset: felt) { let word_dict = memory.word_dict; - // Compute new words_len. - let (required_words_len, _) = unsigned_div_rem(offset + 32 + 31, 32); - let fits = is_le(required_words_len, memory.words_len); - let new_words_len = fits * memory.words_len + (1 - fits) * required_words_len; - // Check alignment of offset to 16B chunks. let (chunk_index, offset_in_chunk) = unsigned_div_rem(offset, 16); @@ -60,7 +55,7 @@ namespace Memory { // so we optimize for it. Note that no locals were allocated at all. dict_write{dict_ptr=word_dict}(chunk_index, element.high); dict_write{dict_ptr=word_dict}(chunk_index + 1, element.low); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } @@ -93,7 +88,7 @@ namespace Memory { dict_write{dict_ptr=word_dict}(chunk_index, new_w0); dict_write{dict_ptr=word_dict}(chunk_index + 1, new_w1); dict_write{dict_ptr=word_dict}(chunk_index + 2, new_w2); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } @@ -113,11 +108,6 @@ namespace Memory { let word_dict = memory.word_dict; - // Compute new words_len. - let (required_words_len, _) = unsigned_div_rem(offset + element_len + 31, 32); - let fits = is_le(required_words_len, memory.words_len); - let new_words_len = fits * memory.words_len + (1 - fits) * required_words_len; - // Check alignment of offset to 16B chunks. let (chunk_index_i, offset_in_chunk_i) = unsigned_div_rem(offset, 16); let (chunk_index_f, offset_in_chunk_f) = unsigned_div_rem(offset + element_len - 1, 16); @@ -134,7 +124,7 @@ namespace Memory { let x = Helpers.bytes_to_felt(element_len, element); let new_w = w_h * mask_i + x * mask_f + w_ll; dict_write{dict_ptr=word_dict}(chunk_index_i, new_w); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } @@ -158,7 +148,7 @@ namespace Memory { chunk_index_i + 1, chunk_index_f, element + 16 - offset_in_chunk_i ); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } @@ -170,11 +160,6 @@ namespace Memory { func load{range_check_ptr, memory: model.Memory*}(offset: felt) -> Uint256 { let word_dict = memory.word_dict; - // Compute new words_len. - let (required_words_len, _) = unsigned_div_rem(offset + 32 + 31, 32); - let fits = is_le(required_words_len, memory.words_len); - let new_words_len = fits * memory.words_len + (1 - fits) * required_words_len; - // Check alignment of offset to 16B chunks. let (chunk_index, offset_in_chunk) = unsigned_div_rem(offset, 16); @@ -183,7 +168,7 @@ namespace Memory { // so we optimize for it. Note that no locals were allocated at all. let (el_h) = dict_read{dict_ptr=word_dict}(chunk_index); let (el_l) = dict_read{dict_ptr=word_dict}(chunk_index + 1); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (Uint256(low=el_l, high=el_h)); } @@ -209,7 +194,7 @@ namespace Memory { let el_h = w0_l * mask_c + w1_h; let el_l = w1_l * mask_c + w2_h; - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (Uint256(low=el_l, high=el_h)); } @@ -224,15 +209,7 @@ namespace Memory { ) { alloc_locals; - // Compute new words_len. - let (required_words_len, _) = unsigned_div_rem(offset + element_len + 31, 32); - let fits = is_le(required_words_len, memory.words_len); - let new_words_len = fits * memory.words_len + (1 - fits) * required_words_len; - if (element_len == 0) { - tempvar memory = new model.Memory( - memory.word_dict_start, memory.word_dict, new_words_len - ); return (); } @@ -251,7 +228,7 @@ namespace Memory { let (_, w_l) = Helpers.div_rem(w, mask_i); let (w_lh, _) = Helpers.div_rem(w_l, mask_f); Helpers.split_word(w_lh, element_len, element); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } @@ -271,7 +248,7 @@ namespace Memory { chunk_index_i + 1, chunk_index_f, element + 16 - offset_in_chunk_i ); - tempvar memory = new model.Memory(memory.word_dict_start, word_dict, new_words_len); + tempvar memory = new model.Memory(memory.word_dict_start, word_dict, memory.words_len); return (); } } diff --git a/src/kakarot/state.cairo b/src/kakarot/state.cairo index e0f06343e..e8ec40fb6 100644 --- a/src/kakarot/state.cairo +++ b/src/kakarot/state.cairo @@ -181,13 +181,33 @@ namespace State { return gas_cost; } - // @dev Checks if an address is warm (has been accessed before or in access list). + // @notice Checks if an address is warm (has been accessed before or in access list). + // @dev This also warms up the account if it's not already warm. // @param address The address to check. // @return A boolean indicating whether the address is warm. - func is_account_warm{state: model.State*}(address: felt) -> felt { + func is_account_warm{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, state: model.State* + }(address: felt) -> felt { alloc_locals; let accounts = state.accounts; let (pointer) = dict_read{dict_ptr=accounts}(key=address); + + // If found in state, the account is warm + if (pointer != 0) { + tempvar state = new model.State( + accounts_start=state.accounts_start, + accounts=accounts, + events_len=state.events_len, + events=state.events, + transfers_len=state.transfers_len, + transfers=state.transfers, + ); + return TRUE; + } + + // Warms up the account + let account = Account.fetch_or_create(address); + dict_write{dict_ptr=accounts}(key=address, new_value=cast(account, felt)); tempvar state = new model.State( accounts_start=state.accounts_start, accounts=accounts, @@ -197,15 +217,12 @@ namespace State { transfers=state.transfers, ); - // If not found in state, the account is not warm - if (pointer != 0) { - return TRUE; - } return FALSE; } // @notice Checks if a storage slot is warm (has been accessed before) in an account. - // @dev Since it reads the storage of the account, it will warm up both the account and the storage. + // @dev Since this is only called in SSTORE/SLOAD opcodes, + // we consider that account and storage will be warmed up during the execution of the opcode. // @param self The account to check. // @param key The key of the storage slot to check. // @return A boolean indicating whether the storage slot is warm. diff --git a/tests/src/kakarot/test_memory.cairo b/tests/src/kakarot/test_memory.cairo index 194003d37..9e13371e1 100644 --- a/tests/src/kakarot/test_memory.cairo +++ b/tests/src/kakarot/test_memory.cairo @@ -58,7 +58,7 @@ func test__load__should_load_an_element_from_the_memory_with_offset{range_check_ return (); } -func test__load__should_expand_memory_and_return_element{range_check_ptr}() { +func test__load__should_return_element{range_check_ptr}() { // Given alloc_locals; let memory = Memory.init(); @@ -70,11 +70,9 @@ func test__load__should_expand_memory_and_return_element{range_check_ptr}() { let value = Memory.load(0); // Then assert value = Uint256(1, 0); - assert memory.words_len = 1; let value = Memory.load(32); } assert value = Uint256(0, 0); - assert memory.words_len = 2; return (); } diff --git a/tests/src/kakarot/test_memory.py b/tests/src/kakarot/test_memory.py index 5ca58d97c..31c968134 100644 --- a/tests/src/kakarot/test_memory.py +++ b/tests/src/kakarot/test_memory.py @@ -34,4 +34,4 @@ async def test_should_load_an_element_from_the_memory_with_offset( ) def test_should_expand_memory_and_return_element(self, cairo_run): - cairo_run("test__load__should_expand_memory_and_return_element") + cairo_run("test__load__should_return_element") diff --git a/tests/src/kakarot/test_state.cairo b/tests/src/kakarot/test_state.cairo index 46f2bd3d3..47b7dcb8e 100644 --- a/tests/src/kakarot/test_state.cairo +++ b/tests/src/kakarot/test_state.cairo @@ -185,7 +185,9 @@ func test___copy_accounts__should_handle_null_pointers{range_check_ptr}() { return (); } -func test__is_account_warm__account_in_state() { +func test__is_account_warm__account_in_state{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr +}() { let evm_address = 'alive'; let starknet_address = 'starknet_alive'; tempvar address = new model.Address(starknet_address, evm_address); @@ -203,7 +205,9 @@ func test__is_account_warm__account_in_state() { return (); } -func test__is_account_warm__account_not_in_state() { +func test__is_account_warm__account_not_in_state{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr +}() { let state = State.init(); let evm_address = 'alive'; with state { @@ -213,6 +217,24 @@ func test__is_account_warm__account_not_in_state() { return (); } +func test__is_account_warm__warms_up_account{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr +}() { + let state = State.init(); + let evm_address = 'alive'; + with state { + let is_warm = State.is_account_warm(evm_address); + } + assert is_warm = 0; + + with state { + let is_warm = State.is_account_warm(evm_address); + } + + assert is_warm = 1; + return (); +} + func test__cache_precompiles{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( ) -> model.State* { alloc_locals; diff --git a/tests/src/kakarot/test_state.py b/tests/src/kakarot/test_state.py index 8dd28601c..6b3c62247 100644 --- a/tests/src/kakarot/test_state.py +++ b/tests/src/kakarot/test_state.py @@ -64,9 +64,14 @@ class TestIsAccountWarm: def test_should_return_true_when_account_in_state(self, cairo_run): cairo_run("test__is_account_warm__account_in_state") + @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) def test_should_return_false_when_account_not_state(self, cairo_run): cairo_run("test__is_account_warm__account_not_in_state") + @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + def test_should_warm_up_account(self, cairo_run): + cairo_run("test__is_account_warm__warms_up_account") + class TestIsStorageWarm: @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) def test_should_return_true_when_already_read(self, cairo_run): diff --git a/tests/utils/serde.py b/tests/utils/serde.py index c9a56c83d..b536c0536 100644 --- a/tests/utils/serde.py +++ b/tests/utils/serde.py @@ -200,9 +200,8 @@ def serialize_stack(self, ptr): def serialize_memory(self, ptr): raw = self.serialize_pointers("model.Memory", ptr) memory_dict = self.serialize_dict(raw["word_dict_start"]) - return "".join( - [f"{memory_dict.get(i, 0):032x}" for i in range(2 * raw["words_len"])] - ) + items_count = len(memory_dict.items()) + return "".join([f"{memory_dict.get(i, 0):032x}" for i in range(items_count)]) def serialize_scope(self, scope, scope_ptr): if scope.path[-1] == "State":