diff --git a/system-contracts/contracts/EvmInterpreterFunctions.template.yul b/system-contracts/contracts/EvmInterpreterFunctions.template.yul index c6f7d0b2f..1e8902721 100644 --- a/system-contracts/contracts/EvmInterpreterFunctions.template.yul +++ b/system-contracts/contracts/EvmInterpreterFunctions.template.yul @@ -39,7 +39,7 @@ function LAST_RETURNDATA_SIZE_OFFSET() -> offset { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -90,71 +90,62 @@ function readBytes(start, maxAcceptablePos,length) -> value { value := shr(mul(8,sub(32,length)),mload(start)) } -function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { +function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if or(iszero(lt(tempSp, BYTECODE_OFFSET())), lt(tempSp, STACK_OFFSET())) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } -function swapStackItem(sp, evmGas, position) -> evmGasLeft { +function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, position)) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } -function popStackItem(sp, evmGasLeft) -> a, newSp { +function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { +function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } -function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) +function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -function pushStackItemWithoutCheck(sp, item) -> newSp { +function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -862,16 +853,15 @@ function _saveReturndataAfterZkEVMCall() { mstore(lastRtSzOffset, returndatasize()) } -function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { +function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -929,7 +919,7 @@ function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function capGas(evmGasLeft,oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 @@ -993,17 +983,16 @@ function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize } } -function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { +function performCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize popStackCheck(oldSp, evmGasLeft, 7) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1062,22 +1051,21 @@ function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp,success, evmGasLeft) + stackHead := success } -function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { +function delegateCall(oldSp, oldIsStatic, evmGasLeft, oldStackHead) -> sp, isStatic, extraCost, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize sp := oldSp isStatic := oldIsStatic popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(sp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1125,7 +1113,7 @@ function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function getMessageCallGas ( @@ -1218,7 +1206,7 @@ function _fetchConstructorReturnGas() -> gasLeft { gasLeft := mload(0) } -function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { +function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld, oldStackHead) -> result, evmGasLeft, stackHead { pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) _eraseReturndataPointer() @@ -1232,10 +1220,10 @@ function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGa offset := add(MEM_OFFSET_INNER(), offset) pushStackCheck(sp, evmGasLeftOld, 4) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) // Selector mstore(sub(offset, 0x80), 0x5b16a23c) @@ -1280,13 +1268,13 @@ function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGa let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -1329,15 +1317,15 @@ function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { } } -function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { +function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 100) let addr, dest, offset, len popStackCheck(oldSp, evmGasLeft, 4) - addr, sp := popStackItemWithoutCheck(oldSp) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -1359,7 +1347,7 @@ function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { } } -function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { +function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1369,9 +1357,8 @@ function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1397,14 +1384,14 @@ function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { let addr := getNewAddress(address()) let result - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } -function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ +function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1414,10 +1401,10 @@ function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr let value, offset, size, salt popStackCheck(oldSp, evmGasLeft, 4) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - salt, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1453,5 +1440,5 @@ function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) } diff --git a/system-contracts/contracts/EvmInterpreterLoop.template.yul b/system-contracts/contracts/EvmInterpreterLoop.template.yul index dc3346988..076e9ff08 100644 --- a/system-contracts/contracts/EvmInterpreterLoop.template.yul +++ b/system-contracts/contracts/EvmInterpreterLoop.template.yul @@ -4,6 +4,7 @@ let sp := sub(STACK_OFFSET(), 32) // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode +let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -17,85 +18,75 @@ for { } true { } { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, add(a, b)) + stackHead := add(a, stackHead) ip := add(ip, 1) } case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - - sp := pushStackItemWithoutCheck(sp, mul(a, b)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) ip := add(ip, 1) } case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sub(a, b)) + stackHead := sub(a, stackHead) ip := add(ip, 1) } case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - sp := pushStackItemWithoutCheck(sp, div(a, b)) ip := add(ip, 1) } case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -104,11 +95,10 @@ for { } true { } { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + stackHead := addmod(a, b, N) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -117,11 +107,10 @@ for { } true { } { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -130,10 +119,9 @@ for { } true { } { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -149,10 +137,9 @@ for { } true { } { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + stackHead := signextend(b, x) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -161,10 +148,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) + stackHead := lt(a, b) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -173,10 +159,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) + stackHead:= gt(a, b) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -185,10 +170,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, slt(a, b)) + stackHead := slt(a, b) ip := add(ip, 1) } case 0x13 { // OP_SGT @@ -197,10 +181,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + stackHead := sgt(a, b) ip := add(ip, 1) } case 0x14 { // OP_EQ @@ -209,10 +192,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, eq(a, b)) + stackHead := eq(a, b) ip := add(ip, 1) } case 0x15 { // OP_ISZERO @@ -221,9 +203,8 @@ for { } true { } { let a popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := iszero(stackHead) - sp := pushStackItemWithoutCheck(sp, iszero(a)) ip := add(ip, 1) } case 0x16 { // OP_AND @@ -232,10 +213,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, and(a,b)) + stackHead := and(a,b) ip := add(ip, 1) } case 0x17 { // OP_OR @@ -244,10 +224,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, or(a,b)) + stackHead := or(a,b) ip := add(ip, 1) } case 0x18 { // OP_XOR @@ -256,21 +235,20 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) + stackHead := xor(a, b) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - sp := pushStackItemWithoutCheck(sp, not(a)) ip := add(ip, 1) } case 0x1A { // OP_BYTE @@ -279,10 +257,9 @@ for { } true { } { let i, x popStackCheck(sp, evmGasLeft, 2) - i, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, byte(i, x)) + stackHead := byte(i, x) ip := add(ip, 1) } case 0x1B { // OP_SHL @@ -291,10 +268,9 @@ for { } true { } { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + stackHead := shl(shift, value) ip := add(ip, 1) } case 0x1C { // OP_SHR @@ -303,10 +279,9 @@ for { } true { } { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + stackHead := shr(shift, value) ip := add(ip, 1) } case 0x1D { // OP_SAR @@ -315,10 +290,9 @@ for { } true { } { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + stackHead := sar(shift, value) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -327,8 +301,7 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -341,13 +314,13 @@ for { } true { } { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE @@ -355,49 +328,54 @@ for { } true { } { let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let i := stackHead - let i - - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) + stackHead := calldataload(i) - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -406,9 +384,9 @@ for { } true { } { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) @@ -431,7 +409,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -441,9 +419,9 @@ for { } true { } { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -466,14 +444,16 @@ for { } true { } { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -481,19 +461,19 @@ for { } true { } { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -501,9 +481,9 @@ for { } true { } { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -522,8 +502,11 @@ for { } true { } { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -532,59 +515,60 @@ for { } true { } { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let blockNumber := stackHead + stackHead := blockhash(blockNumber) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -592,22 +576,24 @@ for { } true { } { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - let memValue := mload(add(MEM_OFFSET_INNER(), offset)) - sp := pushStackItemWithoutCheck(sp, memValue) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -616,8 +602,8 @@ for { } true { } { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -632,8 +618,8 @@ for { } true { } { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -648,7 +634,10 @@ for { } true { } { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -662,7 +651,8 @@ for { } true { } { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value + ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -675,8 +665,8 @@ for { } true { } { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -713,7 +703,7 @@ for { } true { } { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -733,8 +723,8 @@ for { } true { } { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -758,7 +748,7 @@ for { } true { } { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -767,13 +757,13 @@ for { } true { } { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -783,11 +773,12 @@ for { } true { } { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let key := stackHead - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(key) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -799,8 +790,8 @@ for { } true { } { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -808,9 +799,9 @@ for { } true { } { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO overflow checks checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -827,7 +818,7 @@ for { } true { } { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -836,7 +827,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -845,7 +836,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -854,7 +845,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -863,7 +854,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -872,7 +863,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -881,7 +872,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -890,7 +881,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -899,7 +890,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -908,7 +899,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -917,7 +908,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -926,7 +917,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -935,7 +926,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -944,7 +935,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -953,7 +944,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -962,7 +953,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -971,7 +962,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -980,7 +971,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -989,7 +980,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -998,7 +989,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -1007,7 +998,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -1016,7 +1007,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -1025,7 +1016,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -1034,7 +1025,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -1043,7 +1034,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -1052,7 +1043,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -1061,7 +1052,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -1070,7 +1061,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -1079,7 +1070,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -1088,7 +1079,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -1097,7 +1088,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -1106,7 +1097,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -1115,135 +1106,136 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } - case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + case 0x80 { // OP_DUP1 + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -1255,8 +1247,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1277,9 +1269,9 @@ for { } true { } { let offset, size, topic1 popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1300,8 +1292,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1314,8 +1306,8 @@ for { } true { } { { let topic1, topic2 popStackCheck(sp, evmGasLeft, 2) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -1329,8 +1321,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1343,9 +1335,9 @@ for { } true { } { { let topic1, topic2, topic3 popStackCheck(sp, evmGasLeft, 3) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -1359,8 +1351,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1373,16 +1365,16 @@ for { } true { } { { let topic1, topic2, topic3, topic4 popStackCheck(sp, evmGasLeft, 4) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -1391,7 +1383,7 @@ for { } true { } { let gasUsed // A function was implemented in order to avoid stack depth errors. - gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + gasUsed, sp, stackHead := performCall(sp, evmGasLeft, isStatic, stackHead) // Check if the following is ok evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -1401,8 +1393,8 @@ for { } true { } { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) @@ -1416,24 +1408,24 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + sp, isStatic, gasUsed, stackHead := delegateCall(sp, isStatic, evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft, gasUsed) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) + gasUsed, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft,gasUsed) ip := add(ip, 1) } @@ -1441,8 +1433,8 @@ for { } true { } { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO invalid? ensureAcceptableMemLocation(offset) diff --git a/system-contracts/contracts/EvmInterpreterPreprocessed.yul b/system-contracts/contracts/EvmInterpreterPreprocessed.yul index 6d1fe6fe9..927318b2d 100644 --- a/system-contracts/contracts/EvmInterpreterPreprocessed.yul +++ b/system-contracts/contracts/EvmInterpreterPreprocessed.yul @@ -108,7 +108,7 @@ object "EVMInterpreter" { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -159,71 +159,62 @@ object "EVMInterpreter" { value := shr(mul(8,sub(32,length)),mload(start)) } - function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if or(iszero(lt(tempSp, BYTECODE_OFFSET())), lt(tempSp, STACK_OFFSET())) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } - function swapStackItem(sp, evmGas, position) -> evmGasLeft { + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, position)) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft) -> a, newSp { + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } - function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItemWithoutCheck(sp, item) -> newSp { + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -931,16 +922,15 @@ object "EVMInterpreter" { mstore(lastRtSzOffset, returndatasize()) } - function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { + function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -998,7 +988,7 @@ object "EVMInterpreter" { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function capGas(evmGasLeft,oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 @@ -1062,17 +1052,16 @@ object "EVMInterpreter" { } } - function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { + function performCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize popStackCheck(oldSp, evmGasLeft, 7) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1131,22 +1120,21 @@ object "EVMInterpreter" { default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp,success, evmGasLeft) + stackHead := success } - function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + function delegateCall(oldSp, oldIsStatic, evmGasLeft, oldStackHead) -> sp, isStatic, extraCost, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize sp := oldSp isStatic := oldIsStatic popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(sp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1194,7 +1182,7 @@ object "EVMInterpreter" { default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function getMessageCallGas ( @@ -1287,7 +1275,7 @@ object "EVMInterpreter" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { + function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld, oldStackHead) -> result, evmGasLeft, stackHead { pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) _eraseReturndataPointer() @@ -1301,10 +1289,10 @@ object "EVMInterpreter" { offset := add(MEM_OFFSET_INNER(), offset) pushStackCheck(sp, evmGasLeftOld, 4) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) // Selector mstore(sub(offset, 0x80), 0x5b16a23c) @@ -1349,13 +1337,13 @@ object "EVMInterpreter" { let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -1398,15 +1386,15 @@ object "EVMInterpreter" { } } - function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 100) let addr, dest, offset, len popStackCheck(oldSp, evmGasLeft, 4) - addr, sp := popStackItemWithoutCheck(oldSp) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -1428,7 +1416,7 @@ object "EVMInterpreter" { } } - function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1438,9 +1426,8 @@ object "EVMInterpreter" { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1466,14 +1453,14 @@ object "EVMInterpreter" { let addr := getNewAddress(address()) let result - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } - function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1483,10 +1470,10 @@ object "EVMInterpreter" { let value, offset, size, salt popStackCheck(oldSp, evmGasLeft, 4) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - salt, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1522,7 +1509,7 @@ object "EVMInterpreter" { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) } @@ -1541,6 +1528,7 @@ object "EVMInterpreter" { // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode + let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -1554,85 +1542,75 @@ object "EVMInterpreter" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, add(a, b)) + stackHead := add(a, stackHead) ip := add(ip, 1) } case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - - sp := pushStackItemWithoutCheck(sp, mul(a, b)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) ip := add(ip, 1) } case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sub(a, b)) + stackHead := sub(a, stackHead) ip := add(ip, 1) } case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - sp := pushStackItemWithoutCheck(sp, div(a, b)) ip := add(ip, 1) } case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -1641,11 +1619,10 @@ object "EVMInterpreter" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + stackHead := addmod(a, b, N) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -1654,11 +1631,10 @@ object "EVMInterpreter" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -1667,10 +1643,9 @@ object "EVMInterpreter" { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -1686,10 +1661,9 @@ object "EVMInterpreter" { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + stackHead := signextend(b, x) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -1698,10 +1672,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) + stackHead := lt(a, b) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -1710,10 +1683,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) + stackHead:= gt(a, b) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -1722,10 +1694,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, slt(a, b)) + stackHead := slt(a, b) ip := add(ip, 1) } case 0x13 { // OP_SGT @@ -1734,10 +1705,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + stackHead := sgt(a, b) ip := add(ip, 1) } case 0x14 { // OP_EQ @@ -1746,10 +1716,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, eq(a, b)) + stackHead := eq(a, b) ip := add(ip, 1) } case 0x15 { // OP_ISZERO @@ -1758,9 +1727,8 @@ object "EVMInterpreter" { let a popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := iszero(stackHead) - sp := pushStackItemWithoutCheck(sp, iszero(a)) ip := add(ip, 1) } case 0x16 { // OP_AND @@ -1769,10 +1737,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, and(a,b)) + stackHead := and(a,b) ip := add(ip, 1) } case 0x17 { // OP_OR @@ -1781,10 +1748,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, or(a,b)) + stackHead := or(a,b) ip := add(ip, 1) } case 0x18 { // OP_XOR @@ -1793,21 +1759,20 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) + stackHead := xor(a, b) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - sp := pushStackItemWithoutCheck(sp, not(a)) ip := add(ip, 1) } case 0x1A { // OP_BYTE @@ -1816,10 +1781,9 @@ object "EVMInterpreter" { let i, x popStackCheck(sp, evmGasLeft, 2) - i, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, byte(i, x)) + stackHead := byte(i, x) ip := add(ip, 1) } case 0x1B { // OP_SHL @@ -1828,10 +1792,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + stackHead := shl(shift, value) ip := add(ip, 1) } case 0x1C { // OP_SHR @@ -1840,10 +1803,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + stackHead := shr(shift, value) ip := add(ip, 1) } case 0x1D { // OP_SAR @@ -1852,10 +1814,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + stackHead := sar(shift, value) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -1864,8 +1825,7 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1878,13 +1838,13 @@ object "EVMInterpreter" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE @@ -1892,49 +1852,54 @@ object "EVMInterpreter" { let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let i := stackHead - let i + stackHead := calldataload(i) - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) - - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -1943,9 +1908,9 @@ object "EVMInterpreter" { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) @@ -1968,7 +1933,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -1978,9 +1943,9 @@ object "EVMInterpreter" { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -2003,14 +1968,16 @@ object "EVMInterpreter" { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -2018,19 +1985,19 @@ object "EVMInterpreter" { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -2038,9 +2005,9 @@ object "EVMInterpreter" { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -2059,8 +2026,11 @@ object "EVMInterpreter" { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -2069,59 +2039,60 @@ object "EVMInterpreter" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let blockNumber := stackHead + stackHead := blockhash(blockNumber) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -2129,22 +2100,24 @@ object "EVMInterpreter" { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - let memValue := mload(add(MEM_OFFSET_INNER(), offset)) - sp := pushStackItemWithoutCheck(sp, memValue) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -2153,8 +2126,8 @@ object "EVMInterpreter" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -2169,8 +2142,8 @@ object "EVMInterpreter" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -2185,7 +2158,10 @@ object "EVMInterpreter" { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -2199,7 +2175,8 @@ object "EVMInterpreter" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value + ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -2212,8 +2189,8 @@ object "EVMInterpreter" { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -2250,7 +2227,7 @@ object "EVMInterpreter" { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -2270,8 +2247,8 @@ object "EVMInterpreter" { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -2295,7 +2272,7 @@ object "EVMInterpreter" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -2304,13 +2281,13 @@ object "EVMInterpreter" { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -2320,11 +2297,12 @@ object "EVMInterpreter" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let key := stackHead - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(key) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -2336,8 +2314,8 @@ object "EVMInterpreter" { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -2345,9 +2323,9 @@ object "EVMInterpreter" { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO overflow checks checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2364,7 +2342,7 @@ object "EVMInterpreter" { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -2373,7 +2351,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -2382,7 +2360,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -2391,7 +2369,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -2400,7 +2378,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -2409,7 +2387,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -2418,7 +2396,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -2427,7 +2405,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -2436,7 +2414,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -2445,7 +2423,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -2454,7 +2432,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -2463,7 +2441,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -2472,7 +2450,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -2481,7 +2459,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -2490,7 +2468,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -2499,7 +2477,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -2508,7 +2486,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -2517,7 +2495,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -2526,7 +2504,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -2535,7 +2513,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -2544,7 +2522,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -2553,7 +2531,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -2562,7 +2540,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -2571,7 +2549,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -2580,7 +2558,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -2589,7 +2567,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -2598,7 +2576,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -2607,7 +2585,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -2616,7 +2594,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -2625,7 +2603,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -2634,7 +2612,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -2643,7 +2621,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -2652,135 +2630,136 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } - case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + case 0x80 { // OP_DUP1 + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -2792,8 +2771,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2814,9 +2793,9 @@ object "EVMInterpreter" { let offset, size, topic1 popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2837,8 +2816,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2851,8 +2830,8 @@ object "EVMInterpreter" { { let topic1, topic2 popStackCheck(sp, evmGasLeft, 2) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -2866,8 +2845,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2880,9 +2859,9 @@ object "EVMInterpreter" { { let topic1, topic2, topic3 popStackCheck(sp, evmGasLeft, 3) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -2896,8 +2875,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2910,16 +2889,16 @@ object "EVMInterpreter" { { let topic1, topic2, topic3, topic4 popStackCheck(sp, evmGasLeft, 4) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -2928,7 +2907,7 @@ object "EVMInterpreter" { let gasUsed // A function was implemented in order to avoid stack depth errors. - gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + gasUsed, sp, stackHead := performCall(sp, evmGasLeft, isStatic, stackHead) // Check if the following is ok evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -2938,8 +2917,8 @@ object "EVMInterpreter" { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) @@ -2953,24 +2932,24 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + sp, isStatic, gasUsed, stackHead := delegateCall(sp, isStatic, evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft, gasUsed) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) + gasUsed, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft,gasUsed) ip := add(ip, 1) } @@ -2978,8 +2957,8 @@ object "EVMInterpreter" { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO invalid? ensureAcceptableMemLocation(offset) @@ -3074,7 +3053,7 @@ object "EVMInterpreter" { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -3125,71 +3104,62 @@ object "EVMInterpreter" { value := shr(mul(8,sub(32,length)),mload(start)) } - function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if or(iszero(lt(tempSp, BYTECODE_OFFSET())), lt(tempSp, STACK_OFFSET())) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } - function swapStackItem(sp, evmGas, position) -> evmGasLeft { + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, position)) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft) -> a, newSp { + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } - function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItemWithoutCheck(sp, item) -> newSp { + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -3897,16 +3867,15 @@ object "EVMInterpreter" { mstore(lastRtSzOffset, returndatasize()) } - function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { + function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -3964,7 +3933,7 @@ object "EVMInterpreter" { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function capGas(evmGasLeft,oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 @@ -4028,17 +3997,16 @@ object "EVMInterpreter" { } } - function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { + function performCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> extraCost, sp, stackHead { let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize popStackCheck(oldSp, evmGasLeft, 7) - gasToPass, sp := popStackItemWithoutCheck(oldSp) - addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -4097,22 +4065,21 @@ object "EVMInterpreter" { default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp,success, evmGasLeft) + stackHead := success } - function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + function delegateCall(oldSp, oldIsStatic, evmGasLeft, oldStackHead) -> sp, isStatic, extraCost, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize sp := oldSp isStatic := oldIsStatic popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) - addr, sp := popStackItemWithoutCheck(sp) - argsOffset, sp := popStackItemWithoutCheck(sp) - argsSize, sp := popStackItemWithoutCheck(sp) - retOffset, sp := popStackItemWithoutCheck(sp) - retSize, sp := popStackItemWithoutCheck(sp) + gasToPass, sp, stackHead := popStackItemWithoutCheck(sp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -4160,7 +4127,7 @@ object "EVMInterpreter" { default { extraCost := add(extraCost, precompileCost) } - sp := pushStackItem(sp, success, evmGasLeft) + stackHead := success } function getMessageCallGas ( @@ -4253,7 +4220,7 @@ object "EVMInterpreter" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { + function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld, oldStackHead) -> result, evmGasLeft, stackHead { pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) _eraseReturndataPointer() @@ -4267,10 +4234,10 @@ object "EVMInterpreter" { offset := add(MEM_OFFSET_INNER(), offset) pushStackCheck(sp, evmGasLeftOld, 4) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) - sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) // Selector mstore(sub(offset, 0x80), 0x5b16a23c) @@ -4315,13 +4282,13 @@ object "EVMInterpreter" { let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -4364,15 +4331,15 @@ object "EVMInterpreter" { } } - function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 100) let addr, dest, offset, len popStackCheck(oldSp, evmGasLeft, 4) - addr, sp := popStackItemWithoutCheck(oldSp) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -4394,7 +4361,7 @@ object "EVMInterpreter" { } } - function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -4404,9 +4371,8 @@ object "EVMInterpreter" { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4432,14 +4398,14 @@ object "EVMInterpreter" { let addr := getNewAddress(address()) let result - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } - function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -4449,10 +4415,10 @@ object "EVMInterpreter" { let value, offset, size, salt popStackCheck(oldSp, evmGasLeft, 4) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - salt, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4488,7 +4454,7 @@ object "EVMInterpreter" { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft, stackHead) } @@ -4507,6 +4473,7 @@ object "EVMInterpreter" { // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode + let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -4520,85 +4487,75 @@ object "EVMInterpreter" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, add(a, b)) + stackHead := add(a, stackHead) ip := add(ip, 1) } case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - - sp := pushStackItemWithoutCheck(sp, mul(a, b)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) ip := add(ip, 1) } case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sub(a, b)) + stackHead := sub(a, stackHead) ip := add(ip, 1) } case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - sp := pushStackItemWithoutCheck(sp, div(a, b)) ip := add(ip, 1) } case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -4607,11 +4564,10 @@ object "EVMInterpreter" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + stackHead := addmod(a, b, N) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -4620,11 +4576,10 @@ object "EVMInterpreter" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -4633,10 +4588,9 @@ object "EVMInterpreter" { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -4652,10 +4606,9 @@ object "EVMInterpreter" { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + stackHead := signextend(b, x) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -4664,10 +4617,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) + stackHead := lt(a, b) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -4676,10 +4628,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) + stackHead:= gt(a, b) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -4688,10 +4639,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, slt(a, b)) + stackHead := slt(a, b) ip := add(ip, 1) } case 0x13 { // OP_SGT @@ -4700,10 +4650,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + stackHead := sgt(a, b) ip := add(ip, 1) } case 0x14 { // OP_EQ @@ -4712,10 +4661,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, eq(a, b)) + stackHead := eq(a, b) ip := add(ip, 1) } case 0x15 { // OP_ISZERO @@ -4724,9 +4672,8 @@ object "EVMInterpreter" { let a popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := iszero(stackHead) - sp := pushStackItemWithoutCheck(sp, iszero(a)) ip := add(ip, 1) } case 0x16 { // OP_AND @@ -4735,10 +4682,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, and(a,b)) + stackHead := and(a,b) ip := add(ip, 1) } case 0x17 { // OP_OR @@ -4747,10 +4693,9 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, or(a,b)) + stackHead := or(a,b) ip := add(ip, 1) } case 0x18 { // OP_XOR @@ -4759,21 +4704,20 @@ object "EVMInterpreter" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) + stackHead := xor(a, b) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - sp := pushStackItemWithoutCheck(sp, not(a)) ip := add(ip, 1) } case 0x1A { // OP_BYTE @@ -4782,10 +4726,9 @@ object "EVMInterpreter" { let i, x popStackCheck(sp, evmGasLeft, 2) - i, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, byte(i, x)) + stackHead := byte(i, x) ip := add(ip, 1) } case 0x1B { // OP_SHL @@ -4794,10 +4737,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + stackHead := shl(shift, value) ip := add(ip, 1) } case 0x1C { // OP_SHR @@ -4806,10 +4748,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + stackHead := shr(shift, value) ip := add(ip, 1) } case 0x1D { // OP_SAR @@ -4818,10 +4759,9 @@ object "EVMInterpreter" { let shift, value popStackCheck(sp, evmGasLeft, 2) - shift, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + stackHead := sar(shift, value) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -4830,8 +4770,7 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4844,13 +4783,13 @@ object "EVMInterpreter" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE @@ -4858,49 +4797,54 @@ object "EVMInterpreter" { let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let i := stackHead - let i + stackHead := calldataload(i) - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) - - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -4909,9 +4853,9 @@ object "EVMInterpreter" { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) @@ -4934,7 +4878,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -4944,9 +4888,9 @@ object "EVMInterpreter" { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -4969,14 +4913,16 @@ object "EVMInterpreter" { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4984,19 +4930,19 @@ object "EVMInterpreter" { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -5004,9 +4950,9 @@ object "EVMInterpreter" { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -5025,8 +4971,11 @@ object "EVMInterpreter" { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -5035,59 +4984,60 @@ object "EVMInterpreter" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + let blockNumber := stackHead + stackHead := blockhash(blockNumber) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -5095,22 +5045,24 @@ object "EVMInterpreter" { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - let memValue := mload(add(MEM_OFFSET_INNER(), offset)) - sp := pushStackItemWithoutCheck(sp, memValue) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -5119,8 +5071,8 @@ object "EVMInterpreter" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -5135,8 +5087,8 @@ object "EVMInterpreter" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -5151,7 +5103,10 @@ object "EVMInterpreter" { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -5165,7 +5120,8 @@ object "EVMInterpreter" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value + ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -5178,8 +5134,8 @@ object "EVMInterpreter" { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -5216,7 +5172,7 @@ object "EVMInterpreter" { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -5236,8 +5192,8 @@ object "EVMInterpreter" { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -5261,7 +5217,7 @@ object "EVMInterpreter" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -5270,13 +5226,13 @@ object "EVMInterpreter" { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -5286,11 +5242,12 @@ object "EVMInterpreter" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let key := stackHead - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(key) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -5302,8 +5259,8 @@ object "EVMInterpreter" { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -5311,9 +5268,9 @@ object "EVMInterpreter" { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO overflow checks checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5330,7 +5287,7 @@ object "EVMInterpreter" { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -5339,7 +5296,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -5348,7 +5305,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -5357,7 +5314,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -5366,7 +5323,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -5375,7 +5332,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -5384,7 +5341,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -5393,7 +5350,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -5402,7 +5359,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -5411,7 +5368,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -5420,7 +5377,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -5429,7 +5386,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -5438,7 +5395,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -5447,7 +5404,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -5456,7 +5413,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -5465,7 +5422,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -5474,7 +5431,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -5483,7 +5440,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -5492,7 +5449,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -5501,7 +5458,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -5510,7 +5467,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -5519,7 +5476,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -5528,7 +5485,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -5537,7 +5494,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -5546,7 +5503,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -5555,7 +5512,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -5564,7 +5521,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -5573,7 +5530,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -5582,7 +5539,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -5591,7 +5548,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -5600,7 +5557,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -5609,7 +5566,7 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -5618,135 +5575,136 @@ object "EVMInterpreter" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } - case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + case 0x80 { // OP_DUP1 + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -5758,8 +5716,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5780,9 +5738,9 @@ object "EVMInterpreter" { let offset, size, topic1 popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5803,8 +5761,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5817,8 +5775,8 @@ object "EVMInterpreter" { { let topic1, topic2 popStackCheck(sp, evmGasLeft, 2) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -5832,8 +5790,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5846,9 +5804,9 @@ object "EVMInterpreter" { { let topic1, topic2, topic3 popStackCheck(sp, evmGasLeft, 3) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -5862,8 +5820,8 @@ object "EVMInterpreter" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5876,16 +5834,16 @@ object "EVMInterpreter" { { let topic1, topic2, topic3, topic4 popStackCheck(sp, evmGasLeft, 4) - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -5894,7 +5852,7 @@ object "EVMInterpreter" { let gasUsed // A function was implemented in order to avoid stack depth errors. - gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + gasUsed, sp, stackHead := performCall(sp, evmGasLeft, isStatic, stackHead) // Check if the following is ok evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -5904,8 +5862,8 @@ object "EVMInterpreter" { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) @@ -5919,24 +5877,24 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + sp, isStatic, gasUsed, stackHead := delegateCall(sp, isStatic, evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft, gasUsed) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL evmGasLeft := chargeGas(evmGasLeft, 100) let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) + gasUsed, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) evmGasLeft := chargeGas(evmGasLeft,gasUsed) ip := add(ip, 1) } @@ -5944,8 +5902,8 @@ object "EVMInterpreter" { let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // TODO invalid? ensureAcceptableMemLocation(offset)