Skip to content

Commit

Permalink
fix(EVM): Make fetchDeployedCode more robust (#1117)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVolosnikov authored Dec 4, 2024
1 parent 6429301 commit ac9e538
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 81 deletions.
112 changes: 58 additions & 54 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand Down
49 changes: 27 additions & 22 deletions system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 2 additions & 5 deletions system-contracts/evm-emulator/EvmEmulatorLoop.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit ac9e538

Please sign in to comment.