Skip to content

Commit

Permalink
Resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
gianbelinche committed Apr 12, 2024
2 parents f112acf + a931717 commit 135de80
Showing 1 changed file with 338 additions and 1 deletion.
339 changes: 338 additions & 1 deletion system-contracts/contracts/EvmInterpreter.yul
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,44 @@ object "EVMInterpreter" {
}
}

function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft {
evmGasLeft := chargeGas(evmGas, 3)
let tempSp := sub(sp, mul(0x20, sub(position, 1)))

if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) {
revert(0, 0)
}

if lt(tempSp, STACK_OFFSET()) {
revert(0, 0)
}

let dup := mload(tempSp)

newSp := add(sp, 0x20)
mstore(newSp, dup)
}

function swapStackItem(sp, evmGas, position) -> evmGasLeft {
evmGasLeft := chargeGas(evmGas, 3)
let tempSp := sub(sp, mul(0x20, position))

if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) {
revert(0, 0)
}

if lt(tempSp, STACK_OFFSET()) {
revert(0, 0)
}


let s2 := mload(sp)
let s1 := mload(tempSp)

mstore(sp, s1)
mstore(tempSp, s2)
}

function popStackItem(sp) -> a, newSp {
// We can not return any error here, because it would break compatibility
if lt(sp, STACK_OFFSET()) {
Expand Down Expand Up @@ -182,16 +220,52 @@ object "EVMInterpreter" {
gasRemaining := sub(prevGas, toCharge)
}

// Note, that this function can overflow. It's up to the caller to ensure that it does not.
function memCost(memSizeWords) -> gasCost {
// The first term of the sum is the quadratic cost, the second one the linear one.
gasCost := add(div(mul(memSizeWords, memSizeWords), 512), mul(3, memSizeWords))
}

// This function can overflow, it is the job of the caller to ensure that it does not.
// The argument to this function is the offset into the memory region IN BYTES.
function expandMemory(newSize) -> gasCost {
let oldSizeInWords := mload(MEM_OFFSET())

// The add 31 here before dividing is there to account for misaligned
// memory expansions, where someone calls this with a newSize that is not
// a multiple of 32. For instance, if someone calls it with an offset of 33,
// the new size in words should be 2, not 1, but dividing by 32 will give 1.
// Adding 31 solves it.
let newSizeInWords := div(add(newSize, 31), 32)

if gt(newSizeInWords, oldSizeInWords) {
// TODO: Check this, it feels like there might be a more optimized way
// of doing this cost calculation.
let oldCost := memCost(oldSizeInWords)
let newCost := memCost(newSizeInWords)

gasCost := sub(newCost, oldCost)
mstore(MEM_OFFSET(), newSizeInWords)
}
}

// Essentially a NOP that will not get optimized away by the compiler
function $llvm_NoInline_llvm$_unoptimized() {
pop(1)
}

function printHex(value) {
mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde)
mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value)
mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681)
$llvm_NoInline_llvm$_unoptimized()
}

function printString(value) {
mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf)
mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value)
mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681)
$llvm_NoInline_llvm$_unoptimized()
}

function isSlotWarm(key) -> isWarm {
Expand Down Expand Up @@ -375,6 +449,171 @@ object "EVMInterpreter" {

sp := pushStackItem(sp, mulmod(a, b, N))
}
case 0x10 { // OP_LT
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, lt(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x11 { // OP_GT
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, gt(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x12 { // OP_SLT
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, slt(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x13 { // OP_SGT
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, sgt(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x14 { // OP_EQ
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, eq(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x15 { // OP_ISZERO
let a

a, sp := popStackItem(sp)

sp := pushStackItem(sp, iszero(a))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x18 { // OP_XOR
let a, b

a, sp := popStackItem(sp)
b, sp := popStackItem(sp)

sp := pushStackItem(sp, xor(a, b))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x19 { // OP_NOT
let a

a, sp := popStackItem(sp)

sp := pushStackItem(sp, not(a))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x1A { // OP_BYTE
let i, x

i, sp := popStackItem(sp)
x, sp := popStackItem(sp)

sp := pushStackItem(sp, byte(i, x))

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x50 { // OP_POP
let _y

_y, sp := popStackItem(sp)

evmGasLeft := chargeGas(evmGasLeft, 2)
}
case 0x51 { // OP_MLOAD
let offset

offset, sp := popStackItem(sp)

let expansionGas := expandMemory(add(offset, 32))

let memValue := mload(add(MEM_OFFSET_INNER(), offset))
sp := pushStackItem(sp, memValue)
evmGasLeft := chargeGas(evmGasLeft, add(3, expansionGas))
}
case 0x52 { // OP_MSTORE
let offset, value

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

let expansionGas := expandMemory(add(offset, 32))

mstore(add(MEM_OFFSET_INNER(), offset), value)
evmGasLeft := chargeGas(evmGasLeft, add(3, expansionGas))
}
case 0x53 { // OP_MSTORE8
let offset, value

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

let expansionGas := expandMemory(add(offset, 1))

mstore8(add(MEM_OFFSET_INNER(), offset), value)
evmGasLeft := chargeGas(evmGasLeft, add(3, expansionGas))
}
// NOTE: We don't currently do full jumpdest validation
// (i.e. validating a jumpdest isn't in PUSH data)
case 0x56 { // OP_JUMP
let counter

counter, sp := popStackItem(sp)

ip := add(add(BYTECODE_OFFSET(), 32), counter)

evmGasLeft := chargeGas(evmGasLeft, 8)

// Check next opcode is JUMPDEST
let nextOpcode := readIP(ip)
if iszero(eq(nextOpcode, 0x5B)) {
revert(0, 0)
}
}
case 0x57 { // OP_JUMPI
let counter, b

counter, sp := popStackItem(sp)
b, sp := popStackItem(sp)

evmGasLeft := chargeGas(evmGasLeft, 10)

if iszero(b) {
continue
}

ip := add(add(BYTECODE_OFFSET(), 32), counter)

// Check next opcode is JUMPDEST
let nextOpcode := readIP(ip)
if iszero(eq(nextOpcode, 0x5B)) {
revert(0, 0)
}
}
case 0x54 { // OP_SLOAD
let key,value,isWarm

Expand All @@ -384,7 +623,7 @@ object "EVMInterpreter" {
switch isWarm
case 0 { evmGasLeft := chargeGas(evmGasLeft,2100) }
default { evmGasLeft := chargeGas(evmGasLeft,100) }

value := sload(key)

sp := pushStackItem(sp,value)
Expand Down Expand Up @@ -420,6 +659,7 @@ object "EVMInterpreter" {
evmGasLeft := chargeGas(evmGasLeft,2)

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

}
Expand All @@ -428,6 +668,7 @@ object "EVMInterpreter" {

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

Expand Down Expand Up @@ -627,6 +868,102 @@ object "EVMInterpreter" {

evmGasLeft := chargeGas(evmGasLeft, 3)
}
case 0x80 { // OP_DUP1
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1)
}
case 0x81 { // OP_DUP2
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2)
}
case 0x82 { // OP_DUP3
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3)
}
case 0x83 { // OP_DUP4
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4)
}
case 0x84 { // OP_DUP5
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5)
}
case 0x85 { // OP_DUP6
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6)
}
case 0x86 { // OP_DUP7
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7)
}
case 0x87 { // OP_DUP8
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8)
}
case 0x88 { // OP_DUP9
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9)
}
case 0x89 { // OP_DUP10
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10)
}
case 0x8A { // OP_DUP11
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11)
}
case 0x8B { // OP_DUP12
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12)
}
case 0x8C { // OP_DUP13
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13)
}
case 0x8D { // OP_DUP14
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14)
}
case 0x8E { // OP_DUP15
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15)
}
case 0x8F { // OP_DUP16
sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16)
}
case 0x90 { // OP_SWAP1
evmGasLeft := swapStackItem(sp, evmGasLeft, 1)
}
case 0x91 { // OP_SWAP2
evmGasLeft := swapStackItem(sp, evmGasLeft, 2)
}
case 0x92 { // OP_SWAP3
evmGasLeft := swapStackItem(sp, evmGasLeft, 3)
}
case 0x93 { // OP_SWAP4
evmGasLeft := swapStackItem(sp, evmGasLeft, 4)
}
case 0x94 { // OP_SWAP5
evmGasLeft := swapStackItem(sp, evmGasLeft, 5)
}
case 0x95 { // OP_SWAP6
evmGasLeft := swapStackItem(sp, evmGasLeft, 6)
}
case 0x96 { // OP_SWAP7
evmGasLeft := swapStackItem(sp, evmGasLeft, 7)
}
case 0x97 { // OP_SWAP8
evmGasLeft := swapStackItem(sp, evmGasLeft, 8)
}
case 0x98 { // OP_SWAP9
evmGasLeft := swapStackItem(sp, evmGasLeft, 9)
}
case 0x99 { // OP_SWAP10
evmGasLeft := swapStackItem(sp, evmGasLeft, 10)
}
case 0x9A { // OP_SWAP11
evmGasLeft := swapStackItem(sp, evmGasLeft, 11)
}
case 0x9B { // OP_SWAP12
evmGasLeft := swapStackItem(sp, evmGasLeft, 12)
}
case 0x9C { // OP_SWAP13
evmGasLeft := swapStackItem(sp, evmGasLeft, 13)
}
case 0x9D { // OP_SWAP14
evmGasLeft := swapStackItem(sp, evmGasLeft, 14)
}
case 0x9E { // OP_SWAP15
evmGasLeft := swapStackItem(sp, evmGasLeft, 15)
}
case 0x9F { // OP_SWAP16
evmGasLeft := swapStackItem(sp, evmGasLeft, 16)
}
// TODO: REST OF OPCODES
default {
// TODO: Revert properly here and report the unrecognized opcode
Expand Down

0 comments on commit 135de80

Please sign in to comment.