Skip to content

Commit

Permalink
Add ADDRESS_MASK in the emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVolosnikov committed Jan 2, 2025
1 parent 4c73482 commit 4b1fc30
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 30 deletions.
44 changes: 24 additions & 20 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ object "EvmEmulator" {
value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
}

function ADDRESS_MASK() -> value { // mask for lower 160 bits
value := 0xffffffffffffffffffffffffffffffffffffffff
}

////////////////////////////////////////////////////////////////
// GENERAL FUNCTIONS
Expand Down Expand Up @@ -575,11 +578,12 @@ object "EvmEmulator" {
// EVM GAS MANAGER FUNCTIONALITY
////////////////////////////////////////////////////////////////

// Address higher bytes must be cleaned before
function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm {
// function warmAccount(address account)
// non-standard selector 0x00
// addr is packed in the same word with selector
mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(0, addr)

performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32)

Expand Down Expand Up @@ -814,11 +818,11 @@ object "EvmEmulator" {
}

function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed {
addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff)

// memory_expansion_cost
gasUsed := expandMemory2(retOffset, retSize, argsOffset, argsSize)

addr := and(rawAddr, ADDRESS_MASK())

let addressAccessCost := 100 // warm address access cost
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
addressAccessCost := 2600 // cold address access cost
Expand Down Expand Up @@ -1126,8 +1130,7 @@ object "EvmEmulator" {

if canBeDeployed {
returndatacopy(0, 0, 32)
addr := mload(0)

addr := and(mload(0), ADDRESS_MASK())
pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts
// so even if constructor reverts, nonce stays incremented and addr stays warm

Expand Down Expand Up @@ -1621,7 +1624,7 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down Expand Up @@ -1764,7 +1767,7 @@ object "EvmEmulator" {

let addr := accessStackHead(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
}
Expand Down Expand Up @@ -1793,15 +1796,14 @@ object "EvmEmulator" {
srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)

// dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost
// minimum_word_size = (size + 31) / 32
let dynamicGas := add(
mul(3, shr(5, add(len, 31))),
expandMemory(dstOffset, len)
)

addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
dynamicGas := add(dynamicGas, 2500)
}
Expand Down Expand Up @@ -1860,7 +1862,7 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down Expand Up @@ -3289,6 +3291,9 @@ object "EvmEmulator" {
value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
}

function ADDRESS_MASK() -> value { // mask for lower 160 bits
value := 0xffffffffffffffffffffffffffffffffffffffff
}

////////////////////////////////////////////////////////////////
// GENERAL FUNCTIONS
Expand Down Expand Up @@ -3676,11 +3681,12 @@ object "EvmEmulator" {
// EVM GAS MANAGER FUNCTIONALITY
////////////////////////////////////////////////////////////////

// Address higher bytes must be cleaned before
function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm {
// function warmAccount(address account)
// non-standard selector 0x00
// addr is packed in the same word with selector
mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(0, addr)

performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32)

Expand Down Expand Up @@ -3915,11 +3921,11 @@ object "EvmEmulator" {
}

function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed {
addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff)

// memory_expansion_cost
gasUsed := expandMemory2(retOffset, retSize, argsOffset, argsSize)

addr := and(rawAddr, ADDRESS_MASK())

let addressAccessCost := 100 // warm address access cost
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
addressAccessCost := 2600 // cold address access cost
Expand Down Expand Up @@ -4227,8 +4233,7 @@ object "EvmEmulator" {

if canBeDeployed {
returndatacopy(0, 0, 32)
addr := mload(0)

addr := and(mload(0), ADDRESS_MASK())
pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts
// so even if constructor reverts, nonce stays incremented and addr stays warm

Expand Down Expand Up @@ -4710,7 +4715,7 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down Expand Up @@ -4853,7 +4858,7 @@ object "EvmEmulator" {

let addr := accessStackHead(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
}
Expand Down Expand Up @@ -4882,15 +4887,14 @@ object "EvmEmulator" {
srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)

// dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost
// minimum_word_size = (size + 31) / 32
let dynamicGas := add(
mul(3, shr(5, add(len, 31))),
expandMemory(dstOffset, len)
)

addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
dynamicGas := add(dynamicGas, 2500)
}
Expand Down Expand Up @@ -4949,7 +4953,7 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down
13 changes: 8 additions & 5 deletions system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ function EMPTY_KECCAK() -> value { // keccak("")
value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
}

function ADDRESS_MASK() -> value { // mask for lower 160 bits
value := 0xffffffffffffffffffffffffffffffffffffffff
}

////////////////////////////////////////////////////////////////
// GENERAL FUNCTIONS
Expand Down Expand Up @@ -515,11 +518,12 @@ function accessStackHead(sp, stackHead) -> value {
// EVM GAS MANAGER FUNCTIONALITY
////////////////////////////////////////////////////////////////

// Address higher bytes must be cleaned before
function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm {
// function warmAccount(address account)
// non-standard selector 0x00
// addr is packed in the same word with selector
mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(0, addr)

performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32)

Expand Down Expand Up @@ -754,11 +758,11 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa
}

function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed {
addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff)

// memory_expansion_cost
gasUsed := expandMemory2(retOffset, retSize, argsOffset, argsSize)

addr := and(rawAddr, ADDRESS_MASK())

let addressAccessCost := 100 // warm address access cost
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
addressAccessCost := 2600 // cold address access cost
Expand Down Expand Up @@ -1066,8 +1070,7 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) ->

if canBeDeployed {
returndatacopy(0, 0, 32)
addr := mload(0)

addr := and(mload(0), ADDRESS_MASK())
pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts
// so even if constructor reverts, nonce stays incremented and addr stays warm

Expand Down
9 changes: 4 additions & 5 deletions system-contracts/evm-emulator/EvmEmulatorLoop.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ for { } true { } {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down Expand Up @@ -452,7 +452,7 @@ for { } true { } {

let addr := accessStackHead(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
}
Expand Down Expand Up @@ -481,15 +481,14 @@ for { } true { } {
srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)
len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead)

addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)

// dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost
// minimum_word_size = (size + 31) / 32
let dynamicGas := add(
mul(3, shr(5, add(len, 31))),
expandMemory(dstOffset, len)
)

addr := and(addr, ADDRESS_MASK())
if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
dynamicGas := add(dynamicGas, 2500)
}
Expand Down Expand Up @@ -548,7 +547,7 @@ for { } true { } {
evmGasLeft := chargeGas(evmGasLeft, 100)

let addr := accessStackHead(sp, stackHead)
addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff)
addr := and(addr, ADDRESS_MASK())

if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) {
evmGasLeft := chargeGas(evmGasLeft, 2500)
Expand Down

0 comments on commit 4b1fc30

Please sign in to comment.