Skip to content

Commit

Permalink
fix(EVM): Make fetchDeployedCode more robust (2) (#1123)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVolosnikov committed Dec 6, 2024
1 parent dedf7f5 commit 19f0e01
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 81 deletions.
114 changes: 60 additions & 54 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -408,29 +408,35 @@ 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 {
returndatacopy(0, 0, 32)
// 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 bytes 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 @@ -1759,11 +1765,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 @@ -3517,29 +3520,35 @@ 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 {
returndatacopy(0, 0, 32)
// 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 bytes 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 @@ -4868,11 +4877,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
50 changes: 28 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,35 @@ 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 {
returndatacopy(0, 0, 32)
// 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 bytes 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 @@ -508,11 +508,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 19f0e01

Please sign in to comment.