From 264c878e465a2edf24dc3fe6ecf0ec8ab4a6f81b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 4 Dec 2024 18:55:54 +0100 Subject: [PATCH] Change fetchDeployedCode logic --- system-contracts/contracts/EvmEmulator.yul | 112 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 49 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 7 +- 3 files changed, 87 insertions(+), 81 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index af87f2aeb..2070e8352 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -408,29 +408,34 @@ object "EvmEmulator" { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. @@ -1726,11 +1731,8 @@ object "EvmEmulator" { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) @@ -3484,29 +3486,34 @@ object "EvmEmulator" { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. @@ -4802,11 +4809,8 @@ object "EvmEmulator" { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 37d9e7cfd..8f948a489 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -346,29 +346,34 @@ function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 20cdc0a2f..33800e619 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -502,11 +502,8 @@ for { } true { } { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen))