Skip to content

Commit

Permalink
Merge pull request matter-labs#341 from lambdaclass/evm-yul-stack-mem…
Browse files Browse the repository at this point in the history
…ory-2

[EVM-Equivalent-YUL] Stack/Memory instructions sload, sstore and msize
  • Loading branch information
jrchatruc authored Apr 12, 2024
2 parents a931717 + 135de80 commit 67fa431
Showing 1 changed file with 85 additions and 3 deletions.
88 changes: 85 additions & 3 deletions system-contracts/contracts/EvmInterpreter.yul
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,44 @@ object "EVMInterpreter" {
$llvm_NoInline_llvm$_unoptimized()
}

function isSlotWarm(key) -> isWarm {
// TODO: Unhardcode this selector 0x482d2e74
mstore8(0, 0x48)
mstore8(1, 0x2d)
mstore8(2, 0x2e)
mstore8(3, 0x74)
mstore(4, key)

let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32)

if iszero(success) {
// This error should never happen
revert(0, 0)
}

isWarm := mload(0)
}

function warmSlot(key,currentValue) -> isWarm, originalValue {
// TODO: Unhardcode this selector 0xbdf78160
mstore8(0, 0xbd)
mstore8(1, 0xf7)
mstore8(2, 0x81)
mstore8(3, 0x60)
mstore(4, key)
mstore(36,currentValue)

let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 64)

if iszero(success) {
// This error should never happen
revert(0, 0)
}

isWarm := mload(0)
originalValue := mload(32)
}

////////////////////////////////////////////////////////////////
// FALLBACK
////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -576,15 +614,59 @@ object "EVMInterpreter" {
revert(0, 0)
}
}
case 0x54 { // OP_SLOAD
let key,value,isWarm

key, sp := popStackItem(sp)

isWarm := isSlotWarm(key)
switch isWarm
case 0 { evmGasLeft := chargeGas(evmGasLeft,2100) }
default { evmGasLeft := chargeGas(evmGasLeft,100) }

value := sload(key)

sp := pushStackItem(sp,value)
}
case 0x55 { // OP_SSTORE
let key, value
let key, value,gasSpent

key, sp := popStackItem(sp)
value, sp := popStackItem(sp)

{
// Here it is okay to read before we charge since we known anyway that
// the context has enough funds to compensate at least for the read.
// Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND);
let currentValue := sload(key)
let wasWarm,originalValue := warmSlot(key,currentValue)
gasSpent := 100
if and(not(eq(value,currentValue)),eq(originalValue,currentValue)) {
switch originalValue
case 0 { gasSpent := 20000}
default { gasSpent := 2900}
}
if iszero(wasWarm) {
gasSpent := add(gasSpent,2100)
}
}

evmGasLeft := chargeGas(evmGasLeft, gasSpent) //gasSpent
sstore(key, value)
// TODO: Handle cold/warm slots and updates, etc for gas costs.
evmGasLeft := chargeGas(evmGasLeft, 100)
}
case 0x59 { // OP_MSIZE
let size
evmGasLeft := chargeGas(evmGasLeft,2)

size := mload(MEM_OFFSET())
size := shl(5,size)
sp := pushStackItem(sp,size)

}
case 0x5A { // OP_GAS (should conflict with yul-environment-1 branch, retain changes in that branch, ditch this one)
evmGasLeft := chargeGas(evmGasLeft, 2)

sp := pushStackItem(sp, evmGasLeft)
}
case 0x5B {} // OP_JUMPDEST
case 0x5F { // OP_PUSH0
Expand Down

0 comments on commit 67fa431

Please sign in to comment.