From 72a86339d444105e4e0e42ee9a7e7e6b3c014147 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 11 Sep 2024 16:25:28 -0300 Subject: [PATCH 1/2] Revert fetch deployed code len optimization --- system-contracts/contracts/EvmInterpreter.yul | 52 ++++++++++++------- .../EvmInterpreterFunctions.template.yul | 24 +++++---- .../EvmInterpreterLoop.template.yul | 4 +- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index 077560eb2..be21b7d12 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -346,16 +346,22 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } @@ -2040,7 +2046,9 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY @@ -3320,16 +3328,22 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } @@ -5014,7 +5028,9 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul index f53c079d8..2e3567f82 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul @@ -264,16 +264,22 @@ function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 - } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 + } + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul index 5880cd1f4..dc3346988 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul @@ -480,7 +480,9 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY From dabe5e2f63e3fcf2bfab37167c3fdbafa2ab35d1 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 11 Sep 2024 16:43:24 -0300 Subject: [PATCH 2/2] Calculate hashes:fix --- system-contracts/SystemContractsHashes.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 9d5a639b2..a27725ce2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -129,8 +129,8 @@ "contractName": "EvmInterpreter", "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", - "bytecodeHash": "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee", - "sourceCodeHash": "0xfc91734d4d37538b19c94be0da51364edd4f6664f0fee383cc2e3b5eeb95336a" + "bytecodeHash": "0x01000cef160515b2631803991c1d49b6b44492406197fb6dc22a8cf05cebd5d5", + "sourceCodeHash": "0x6c1e3d4c2f94342792df4fc671a0929fbb2d5aba1b5e388c70f4dc1ee96cfa74" }, { "contractName": "CodeOracle",