UNPKG

@polygon-hermez/vm

Version:
1,356 lines 49.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handlers = void 0; const ethereumjs_util_1 = require("ethereumjs-util"); const util_1 = require("./util"); const exceptions_1 = require("../../exceptions"); const { smtUtils } = require('@polygon-hermez/zkevm-commonjs'); // the opcode functions exports.handlers = new Map([ // 0x00: STOP [ 0x00, function (runState) { runState.vcm.computeFunctionCounters('opStop', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); (0, util_1.trap)(exceptions_1.ERROR.STOP); }, ], // 0x01: ADD [ 0x01, function (runState) { runState.vcm.computeFunctionCounters('opAdd', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.add(b).mod(ethereumjs_util_1.TWO_POW256); runState.stack.push(r); }, ], // 0x02: MUL [ 0x02, function (runState) { runState.vcm.computeFunctionCounters('opMul', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.mul(b).mod(ethereumjs_util_1.TWO_POW256); runState.stack.push(r); }, ], // 0x03: SUB [ 0x03, function (runState) { runState.vcm.computeFunctionCounters('opSub', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.sub(b).toTwos(256); runState.stack.push(r); }, ], // 0x04: DIV [ 0x04, function (runState) { runState.vcm.computeFunctionCounters('opDiv', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); let r; if (b.isZero()) { r = new ethereumjs_util_1.BN(b); } else { r = a.div(b); } runState.stack.push(r); }, ], // 0x05: SDIV [ 0x05, function (runState) { runState.vcm.computeFunctionCounters('opSDiv', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); let [a, b] = runState.stack.popN(2); let r; if (b.isZero()) { r = new ethereumjs_util_1.BN(b); } else { a = a.fromTwos(256); b = b.fromTwos(256); r = a.div(b).toTwos(256); } runState.stack.push(r); }, ], // 0x06: MOD [ 0x06, function (runState) { runState.vcm.computeFunctionCounters('opMod', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); let r; if (b.isZero()) { r = new ethereumjs_util_1.BN(b); } else { r = a.mod(b); } runState.stack.push(r); }, ], // 0x07: SMOD [ 0x07, function (runState) { runState.vcm.computeFunctionCounters('opSMod', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); let [a, b] = runState.stack.popN(2); let r; if (b.isZero()) { r = new ethereumjs_util_1.BN(b); } else { a = a.fromTwos(256); b = b.fromTwos(256); r = a.abs().mod(b.abs()); if (a.isNeg()) { r = r.ineg(); } r = r.toTwos(256); } runState.stack.push(r); }, ], // 0x08: ADDMOD [ 0x08, function (runState) { runState.vcm.computeFunctionCounters('opAddMod', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b, c] = runState.stack.popN(3); let r; if (c.isZero()) { r = new ethereumjs_util_1.BN(c); } else { r = a.add(b).mod(c); } runState.stack.push(r); }, ], // 0x09: MULMOD [ 0x09, function (runState) { runState.vcm.computeFunctionCounters('opMulMod', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b, c] = runState.stack.popN(3); let r; if (c.isZero()) { r = new ethereumjs_util_1.BN(c); } else { r = a.mul(b).mod(c); } runState.stack.push(r); }, ], // 0x0a: EXP [ 0x0a, function (runState, common) { const [base, exponent] = runState.stack.popN(2); runState.vcm.computeFunctionCounters('opExp', { bytesExponentLength: exponent.toArrayLike(Buffer).length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); if (exponent.isZero()) { runState.stack.push(new ethereumjs_util_1.BN(1)); return; } const byteLength = exponent.byteLength(); if (byteLength < 1 || byteLength > 32) { (0, util_1.trap)(exceptions_1.ERROR.OUT_OF_RANGE); } const gasPrice = common.param('gasPrices', 'expByte'); const amount = new ethereumjs_util_1.BN(byteLength).muln(gasPrice); runState.eei.useGas(amount, 'EXP opcode'); if (base.isZero()) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } const m = ethereumjs_util_1.BN.red(ethereumjs_util_1.TWO_POW256); const redBase = base.toRed(m); const r = redBase.redPow(exponent); runState.stack.push(r.fromRed()); }, ], // 0x0b: SIGNEXTEND [ 0x0b, function (runState) { runState.vcm.computeFunctionCounters('opSignExtend', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); /* eslint-disable-next-line prefer-const */ let [k, val] = runState.stack.popN(2); if (k.ltn(31)) { const signBit = k.muln(8).iaddn(7).toNumber(); const mask = new ethereumjs_util_1.BN(1).ishln(signBit).isubn(1); if (val.testn(signBit)) { val = val.or(mask.notn(256)); } else { val = val.and(mask); } } else { // return the same value val = new ethereumjs_util_1.BN(val); } runState.stack.push(val); }, ], // 0x10 range - bit ops // 0x10: LT [ 0x10, function (runState) { runState.vcm.computeFunctionCounters('opLT', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = new ethereumjs_util_1.BN(a.lt(b) ? 1 : 0); runState.stack.push(r); }, ], // 0x11: GT [ 0x11, function (runState) { runState.vcm.computeFunctionCounters('opGT', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = new ethereumjs_util_1.BN(a.gt(b) ? 1 : 0); runState.stack.push(r); }, ], // 0x12: SLT [ 0x12, function (runState) { runState.vcm.computeFunctionCounters('opSLT', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = new ethereumjs_util_1.BN(a.fromTwos(256).lt(b.fromTwos(256)) ? 1 : 0); runState.stack.push(r); }, ], // 0x13: SGT [ 0x13, function (runState) { runState.vcm.computeFunctionCounters('opSGT', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = new ethereumjs_util_1.BN(a.fromTwos(256).gt(b.fromTwos(256)) ? 1 : 0); runState.stack.push(r); }, ], // 0x14: EQ [ 0x14, function (runState) { runState.vcm.computeFunctionCounters('opEq', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = new ethereumjs_util_1.BN(a.eq(b) ? 1 : 0); runState.stack.push(r); }, ], // 0x15: ISZERO [ 0x15, function (runState) { runState.vcm.computeFunctionCounters('opIsZero', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const a = runState.stack.pop(); const r = new ethereumjs_util_1.BN(a.isZero() ? 1 : 0); runState.stack.push(r); }, ], // 0x16: AND [ 0x16, function (runState) { runState.vcm.computeFunctionCounters('opAnd', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.and(b); runState.stack.push(r); }, ], // 0x17: OR [ 0x17, function (runState) { runState.vcm.computeFunctionCounters('opOr', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.or(b); runState.stack.push(r); }, ], // 0x18: XOR [ 0x18, function (runState) { runState.vcm.computeFunctionCounters('opXor', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); const r = a.xor(b); runState.stack.push(r); }, ], // 0x19: NOT [ 0x19, function (runState) { runState.vcm.computeFunctionCounters('opNot', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const a = runState.stack.pop(); const r = a.notn(256); runState.stack.push(r); }, ], // 0x1a: BYTE [ 0x1a, function (runState) { runState.vcm.computeFunctionCounters('opByte', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [pos, word] = runState.stack.popN(2); if (pos.gten(32)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } const r = new ethereumjs_util_1.BN(word.shrn((31 - pos.toNumber()) * 8).andln(0xff)); runState.stack.push(r); }, ], // 0x1b: SHL [ 0x1b, function (runState) { runState.vcm.computeFunctionCounters('opSHL', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); if (a.gten(256)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } const r = b.shln(a.toNumber()).iand(ethereumjs_util_1.MAX_INTEGER); runState.stack.push(r); }, ], // 0x1c: SHR [ 0x1c, function (runState) { runState.vcm.computeFunctionCounters('opSHR', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); if (a.gten(256)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } const r = b.shrn(a.toNumber()); runState.stack.push(r); }, ], // 0x1d: SAR [ 0x1d, function (runState) { runState.vcm.computeFunctionCounters('opSAR', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [a, b] = runState.stack.popN(2); let r; const isSigned = b.testn(255); if (a.gten(256)) { if (isSigned) { r = new ethereumjs_util_1.BN(ethereumjs_util_1.MAX_INTEGER); } else { r = new ethereumjs_util_1.BN(0); } runState.stack.push(r); return; } const c = b.shrn(a.toNumber()); if (isSigned) { const shiftedOutWidth = 255 - a.toNumber(); const mask = ethereumjs_util_1.MAX_INTEGER.shrn(shiftedOutWidth).shln(shiftedOutWidth); r = c.ior(mask); } else { r = c; } runState.stack.push(r); }, ], // 0x20 range - crypto // 0x20: SHA3 [ 0x20, function (runState) { const [offset, length] = runState.stack.popN(2); runState.vcm.computeFunctionCounters('opSha3', { inputSize: length.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); let data = Buffer.alloc(0); if (!length.isZero()) { data = runState.memory.read(offset.toNumber(), length.toNumber()); } const r = new ethereumjs_util_1.BN((0, ethereumjs_util_1.keccak256)(data)); runState.stack.push(r); }, ], // 0x30 range - closure state // 0x30: ADDRESS [ 0x30, function (runState) { runState.vcm.computeFunctionCounters('opAddress', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const address = new ethereumjs_util_1.BN(runState.eei.getAddress().buf); runState.stack.push(address); }, ], // 0x31: BALANCE [ 0x31, async function (runState) { runState.vcm.computeFunctionCounters('opBalance', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const addressBN = runState.stack.pop(); const address = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(addressBN)); const balance = await runState.eei.getExternalBalance(address); runState.stack.push(balance); }, ], // 0x32: ORIGIN [ 0x32, function (runState) { runState.vcm.computeFunctionCounters('opOrigin', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getTxOrigin()); }, ], // 0x33: CALLER [ 0x33, function (runState) { runState.vcm.computeFunctionCounters('opCaller', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getCaller()); }, ], // 0x34: CALLVALUE [ 0x34, function (runState) { runState.vcm.computeFunctionCounters('opCallValue', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getCallValue()); }, ], // 0x35: CALLDATALOAD [ 0x35, function (runState) { runState.vcm.computeFunctionCounters('opCalldataLoad', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const pos = runState.stack.pop(); if (pos.gt(runState.eei.getCallDataSize())) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } const i = pos.toNumber(); let loaded = runState.eei.getCallData().slice(i, i + 32); loaded = loaded.length ? loaded : Buffer.from([0]); const r = new ethereumjs_util_1.BN((0, ethereumjs_util_1.setLengthRight)(loaded, 32)); runState.stack.push(r); }, ], // 0x36: CALLDATASIZE [ 0x36, function (runState) { runState.vcm.computeFunctionCounters('opCalldataSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const r = runState.eei.getCallDataSize(); runState.stack.push(r); }, ], // 0x37: CALLDATACOPY [ 0x37, function (runState) { const [memOffset, dataOffset, dataLength] = runState.stack.popN(3); if (!dataLength.eqn(0)) { const data = (0, util_1.getDataSlice)(runState.eei.getCallData(), dataOffset, dataLength); runState.vcm.computeFunctionCounters('opCalldataCopy', { inputSize: data.length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const memOffsetNum = memOffset.toNumber(); const dataLengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, dataLengthNum); runState.memory.write(memOffsetNum, dataLengthNum, data); } }, ], // 0x38: CODESIZE [ 0x38, function (runState) { runState.vcm.computeFunctionCounters('opCodeSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getCodeSize()); }, ], // 0x39: CODECOPY [ 0x39, function (runState) { const [memOffset, codeOffset, dataLength] = runState.stack.popN(3); if (!dataLength.eqn(0)) { const data = (0, util_1.getDataSlice)(runState.eei.getCode(), codeOffset, dataLength); runState.vcm.computeFunctionCounters('opCodeCopy', { inputSize: data.length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const memOffsetNum = memOffset.toNumber(); const lengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, lengthNum); runState.memory.write(memOffsetNum, lengthNum, data); } }, ], // 0x3b: EXTCODESIZE [ 0x3b, async function (runState) { runState.vcm.computeFunctionCounters('opExtCodeSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const addressBN = runState.stack.pop(); const size = await runState.eei.getExternalCodeSize(addressBN); runState.stack.push(size); }, ], // 0x3c: EXTCODECOPY [ 0x3c, async function (runState) { const [addressBN, memOffset, codeOffset, dataLength] = runState.stack.popN(4); if (!dataLength.eqn(0)) { const code = await runState.eei.getExternalCode(addressBN); const data = (0, util_1.getDataSlice)(code, codeOffset, dataLength); runState.vcm.computeFunctionCounters('opExtCodeCopy', { inputSize: data.length, bytecodeLen: code.length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const memOffsetNum = memOffset.toNumber(); const lengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, lengthNum); runState.memory.write(memOffsetNum, lengthNum, data); } }, ], // 0x3f: EXTCODEHASH [ 0x3f, async function (runState) { runState.vcm.computeFunctionCounters('opExtCodeHash', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const addressBN = runState.stack.pop(); const code = await runState.eei.getExternalCode(addressBN); if (code.length === 0) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } // Use linear poseidon hash const lpCode = await smtUtils.hashContractBytecode(code.toString('hex')); runState.stack.push(new ethereumjs_util_1.BN(lpCode.slice(2), 16)); }, ], // 0x3d: RETURNDATASIZE [ 0x3d, function (runState) { runState.vcm.computeFunctionCounters('opReturnDataSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getReturnDataSize()); }, ], // 0x3e: RETURNDATACOPY [ 0x3e, function (runState) { const [memOffset, returnDataOffset, dataLength] = runState.stack.popN(3); if (!dataLength.eqn(0)) { const data = (0, util_1.getDataSlice)(runState.eei.getReturnData(), returnDataOffset, dataLength); runState.vcm.computeFunctionCounters('opReturnDataCopy', { inputSize: data.length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const memOffsetNum = memOffset.toNumber(); const lengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, lengthNum); runState.memory.write(memOffsetNum, lengthNum, data); } }, ], // 0x3a: GASPRICE [ 0x3a, function (runState) { runState.vcm.computeFunctionCounters('opGasPrice', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getTxGasPrice()); }, ], // '0x40' range - block operations // 0x40: BLOCKHASH [ 0x40, async function (runState) { runState.vcm.computeFunctionCounters('opBlockHash', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const number = runState.stack.pop(); const hash = await runState.eei.getBatchHash(number); runState.stack.push(hash); }, ], // 0x41: COINBASE [ 0x41, function (runState) { runState.vcm.computeFunctionCounters('opCoinbase', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getBlockCoinbase()); }, ], // 0x42: TIMESTAMP [ 0x42, function (runState) { runState.vcm.computeFunctionCounters('opTimestamp', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getBlockTimestamp()); }, ], // 0x43: NUMBER [ 0x43, async function (runState) { runState.vcm.computeFunctionCounters('opNumber', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const num = await runState.eei.getBlockNum(); runState.stack.push(num); }, ], // 0x44: DIFFICULTY [ 0x44, function (runState) { runState.vcm.computeFunctionCounters('opDifficulty', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getBlockDifficulty()); }, ], // 0x45: GASLIMIT [ 0x45, function (runState) { runState.vcm.computeFunctionCounters('opGasLimit', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getBlockGasLimit()); }, ], // 0x46: CHAINID [ 0x46, function (runState) { runState.vcm.computeFunctionCounters('opChainId', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getChainId()); }, ], // 0x47: SELFBALANCE [ 0x47, function (runState) { runState.vcm.computeFunctionCounters('opSelfBalance', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getSelfBalance()); }, ], // 0x48: BASEFEE [ 0x48, function (runState) { runState.vcm.computeFunctionCounters('opBaseFee', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.eei.getBlockBaseFee()); //runState.stack.push(new BN(0)) }, ], // 0x50 range - 'storage' and execution // 0x50: POP [ 0x50, function (runState) { runState.vcm.computeFunctionCounters('opPop', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.pop(); }, ], // 0x51: MLOAD [ 0x51, function (runState) { runState.vcm.computeFunctionCounters('opMLoad', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const pos = runState.stack.pop(); const word = runState.memory.read(pos.toNumber(), 32); runState.stack.push(new ethereumjs_util_1.BN(word)); }, ], // 0x52: MSTORE [ 0x52, function (runState) { runState.vcm.computeFunctionCounters('opMStore', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [offset, word] = runState.stack.popN(2); const buf = word.toArrayLike(Buffer, 'be', 32); const offsetNum = offset.toNumber(); runState.memory.extend(offsetNum, 32); runState.memory.write(offsetNum, 32, buf); }, ], // 0x53: MSTORE8 [ 0x53, function (runState) { runState.vcm.computeFunctionCounters('opMStore8', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [offset, byte] = runState.stack.popN(2); // NOTE: we're using a 'trick' here to get the least significant byte // NOTE: force cast necessary because `BN.andln` returns number but // the types are wrong const buf = Buffer.from([byte.andln(0xff)]); const offsetNum = offset.toNumber(); runState.memory.extend(offsetNum, 1); runState.memory.write(offsetNum, 1, buf); }, ], // 0x54: SLOAD [ 0x54, async function (runState) { runState.vcm.computeFunctionCounters('opSLoad', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const key = runState.stack.pop(); const keyBuf = key.toArrayLike(Buffer, 'be', 32); const value = await runState.eei.storageLoad(keyBuf); const valueBN = value.length ? new ethereumjs_util_1.BN(value) : new ethereumjs_util_1.BN(0); runState.stack.push(valueBN); }, ], // 0x55: SSTORE [ 0x55, async function (runState) { runState.vcm.computeFunctionCounters('opSStore', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [key, val] = runState.stack.popN(2); const keyBuf = key.toArrayLike(Buffer, 'be', 32); // NOTE: this should be the shortest representation let value; if (val.isZero()) { value = Buffer.from([]); } else { value = val.toArrayLike(Buffer, 'be'); } await runState.eei.storageStore(keyBuf, value); }, ], // 0x56: JUMP [ 0x56, function (runState) { runState.vcm.computeFunctionCounters('opJump', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const dest = runState.stack.pop(); if (dest.gt(runState.eei.getCodeSize())) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMP + ' at ' + (0, util_1.describeLocation)(runState)); } const destNum = dest.toNumber(); if (!(0, util_1.jumpIsValid)(runState, destNum)) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMP + ' at ' + (0, util_1.describeLocation)(runState)); } runState.programCounter = destNum; }, ], // 0x57: JUMPI [ 0x57, function (runState) { runState.vcm.computeFunctionCounters('opJumpI', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const [dest, cond] = runState.stack.popN(2); if (!cond.isZero()) { if (dest.gt(runState.eei.getCodeSize())) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMP + ' at ' + (0, util_1.describeLocation)(runState)); } const destNum = dest.toNumber(); if (!(0, util_1.jumpIsValid)(runState, destNum)) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMP + ' at ' + (0, util_1.describeLocation)(runState)); } runState.programCounter = destNum; } }, ], // 0x58: PC [ 0x58, function (runState) { runState.vcm.computeFunctionCounters('opPC', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(new ethereumjs_util_1.BN(runState.programCounter - 1)); }, ], // 0x59: MSIZE [ 0x59, function (runState) { runState.vcm.computeFunctionCounters('opMSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(runState.memoryWordCount.muln(32)); }, ], // 0x5a: GAS [ 0x5a, function (runState) { runState.vcm.computeFunctionCounters('opGas', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(new ethereumjs_util_1.BN(runState.eei.getGasLeft())); }, ], // 0x5b: JUMPDEST [ 0x5b, function (runState) { runState.vcm.computeFunctionCounters('opJumpDest', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); }, ], // 0x5c: BEGINSUB [ 0x5c, function (runState) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_BEGINSUB + ' at ' + (0, util_1.describeLocation)(runState)); }, ], // 0x5d: RETURNSUB [ 0x5d, function (runState) { if (runState.returnStack.length < 1) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_RETURNSUB); } const dest = runState.returnStack.pop(); runState.programCounter = dest.toNumber(); }, ], // 0x5e: JUMPSUB [ 0x5e, function (runState) { const dest = runState.stack.pop(); if (dest.gt(runState.eei.getCodeSize())) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMPSUB + ' at ' + (0, util_1.describeLocation)(runState)); } const destNum = dest.toNumber(); if (!(0, util_1.jumpSubIsValid)(runState, destNum)) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMPSUB + ' at ' + (0, util_1.describeLocation)(runState)); } runState.returnStack.push(new ethereumjs_util_1.BN(runState.programCounter)); runState.programCounter = destNum + 1; }, ], // 0x5f: PUSH0 [ 0x5f, function (runState) { runState.vcm.computeFunctionCounters('opPush0', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); runState.stack.push(new ethereumjs_util_1.BN(0)); }, ], // 0x60: PUSH [ 0x60, function (runState) { const numToPush = runState.opCode - 0x5f; runState.vcm.computeFunctionCounters('_opPush', { pushBytes: numToPush, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const loaded = new ethereumjs_util_1.BN(runState.eei.getCode().slice(runState.programCounter, runState.programCounter + numToPush)); runState.programCounter += numToPush; runState.stack.push(loaded); }, ], // 0x80: DUP [ 0x80, function (runState) { runState.vcm.computeFunctionCounters('_opDup', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const stackPos = runState.opCode - 0x7f; runState.stack.dup(stackPos); }, ], // 0x90: SWAP [ 0x90, function (runState) { runState.vcm.computeFunctionCounters('_opSwap', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const stackPos = runState.opCode - 0x8f; runState.stack.swap(stackPos); }, ], // 0xa0: LOG [ 0xa0, function (runState) { const [memOffset, memLength] = runState.stack.popN(2); runState.vcm.computeFunctionCounters('_opLog', { inputSize: memLength.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const topicsCount = runState.opCode - 0xa0; const topics = runState.stack.popN(topicsCount); const topicsBuf = topics.map(function (a) { return a.toArrayLike(Buffer, 'be', 32); }); let mem = Buffer.alloc(0); if (!memLength.isZero()) { mem = runState.memory.read(memOffset.toNumber(), memLength.toNumber()); } runState.eei.log(mem, topicsCount, topicsBuf); }, ], // '0xf0' range - closures // 0xf0: CREATE [ 0xf0, async function (runState) { const [value, offset, length] = runState.stack.popN(3); runState.vcm.computeFunctionCounters('opCreate', { bytesNonceLength: runState.eei._env.contract.nonce.addn(1).toArrayLike(Buffer).length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: length.toNumber(), }); const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; let data = Buffer.alloc(0); if (!length.isZero()) { data = runState.memory.read(offset.toNumber(), length.toNumber()); } const ret = await runState.eei.create(gasLimit, value, data); runState.stack.push(ret.returnCode); if (typeof ret.results !== 'undefined') { // If there is execution result (the create has been executed), we need to compute _processContractCall counters runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: length.toNumber(), isDeploy: false, isCreate: true, isCreate2: false, }); } return ret.results; }, ], // 0xf5: CREATE2 [ 0xf5, async function (runState) { if (runState.eei.isStatic()) { (0, util_1.trap)(exceptions_1.ERROR.STATIC_STATE_CHANGE); } const [value, offset, length, salt] = runState.stack.popN(4); runState.vcm.computeFunctionCounters('opCreate2', { bytesNonceLength: runState.eei._env.contract.nonce.addn(1).toArrayLike(Buffer).length, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: length.toNumber(), }); runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: length.toNumber(), isDeploy: false, isCreate: false, isCreate2: true, }); const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; let data = Buffer.alloc(0); if (!length.isZero()) { data = runState.memory.read(offset.toNumber(), length.toNumber()); } const ret = await runState.eei.create2(gasLimit, value, data, salt.toArrayLike(Buffer, 'be', 32)); runState.stack.push(ret.returnCode); return ret.results; }, ], // 0xf1: CALL [ 0xf1, async function (runState) { const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7); const toAddress = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(toAddr)); const bytecodeLength = await runState.eei.getExternalCodeSize(toAddr); runState.vcm.computeFunctionCounters('opCall', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: inLength.toNumber(), outLength: outLength.toNumber(), }); runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: bytecodeLength.toNumber(), isDeploy: false, isCreate: false, isCreate2: false, }); let data = Buffer.alloc(0); if (!inLength.isZero()) { data = runState.memory.read(inOffset.toNumber(), inLength.toNumber()); } const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; const ret = await runState.eei.call(gasLimit, toAddress, value, data, outLength); // Write return data to memory (0, util_1.writeCallOutput)(runState, outOffset, outLength); runState.stack.push(ret.returnCode); return ret.results; }, ], // 0xf2: CALLCODE [ 0xf2, async function (runState) { const [_currentGasLimit, toAddr, value, inOffset, inLength, outOffset, outLength] = runState.stack.popN(7); const toAddress = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(toAddr)); runState.vcm.computeFunctionCounters('opCallCode', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: inLength.toNumber(), outLength: outLength.toNumber(), }); const bytecodeLength = await runState.eei.getExternalCodeSize(toAddr); runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: bytecodeLength.toNumber(), isDeploy: false, isCreate: false, isCreate2: false, }); const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; let data = Buffer.alloc(0); if (!inLength.isZero()) { data = runState.memory.read(inOffset.toNumber(), inLength.toNumber()); } const ret = await runState.eei.callCode(gasLimit, toAddress, value, data, outLength); // Write return data to memory (0, util_1.writeCallOutput)(runState, outOffset, outLength); runState.stack.push(ret.returnCode); return ret.results; }, ], // 0xf4: DELEGATECALL [ 0xf4, async function (runState) { const value = runState.eei.getCallValue(); const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6); const toAddress = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(toAddr)); const bytecodeLength = await runState.eei.getExternalCodeSize(toAddr); runState.vcm.computeFunctionCounters('opDelegateCall', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: inLength.toNumber(), outLength: outLength.toNumber(), }); runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: bytecodeLength.toNumber(), isDeploy: false, isCreate: false, isCreate2: false, }); let data = Buffer.alloc(0); if (!inLength.isZero()) { data = runState.memory.read(inOffset.toNumber(), inLength.toNumber()); } const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; const ret = await runState.eei.callDelegate(gasLimit, toAddress, value, data, outLength); // Write return data to memory (0, util_1.writeCallOutput)(runState, outOffset, outLength); runState.stack.push(ret.returnCode); return ret.results; }, ], // 0x06: STATICCALL [ 0xfa, async function (runState) { const value = new ethereumjs_util_1.BN(0); const [_currentGasLimit, toAddr, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6); const toAddress = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(toAddr)); const bytecodeLength = await runState.eei.getExternalCodeSize(toAddr); runState.vcm.computeFunctionCounters('opStaticCall', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, inLength: inLength.toNumber(), outLength: outLength.toNumber(), }); runState.vcm.computeFunctionCounters('_processContractCall', { bytecodeLength: bytecodeLength.toNumber(), isDeploy: false, isCreate: false, isCreate2: false, }); const gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; let data = Buffer.alloc(0); if (!inLength.isZero()) { data = runState.memory.read(inOffset.toNumber(), inLength.toNumber()); } const ret = await runState.eei.callStatic(gasLimit, toAddress, value, data, outLength); // Write return data to memory (0, util_1.writeCallOutput)(runState, outOffset, outLength); runState.stack.push(ret.returnCode); return ret.results; }, ], // 0xf3: RETURN [ 0xf3, function (runState) { const [offset, length] = runState.stack.popN(2); runState.vcm.computeFunctionCounters('opReturn', { returnLength: length.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, depth: runState.eei._env.depth, }); let returnData = Buffer.alloc(0); if (!length.isZero()) { returnData = runState.memory.read(offset.toNumber(), length.toNumber()); } runState.eei.finish(returnData); }, ], // 0xfd: REVERT [ 0xfd, function (runState) { const [offset, length] = runState.stack.popN(2); runState.vcm.computeFunctionCounters('opRevert', { revertSize: length.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); let returnData = Buffer.alloc(0); if (!length.isZero()) { returnData = runState.memory.read(offset.toNumber(), length.toNumber()); } runState.eei.revert(returnData); }, ], // '0x70', range - other // 0xff: SELFDESTRUCT [ 0xff, async function (runState) { runState.vcm.computeFunctionCounters('opSendAll', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); const selfdestructToAddressBN = runState.stack.pop(); const selfdestructToAddress = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(selfdestructToAddressBN)); return runState.eei.selfDestruct(selfdestructToAddress); }, ], ]); // Fill in rest of PUSHn, DUPn, SWAPn, LOGn for handlers const pushFn = exports.handlers.get(0x60); for (let i = 0x61; i <= 0x7f; i++) { exports.handlers.set(i, pushFn); } const dupFn = exports.handlers.get(0x80); for (let i = 0x81; i <= 0x8f; i++) { exports.handlers.set(i, dupFn); } const swapFn = exports.handlers.get(0x90); for (let i = 0x91; i <= 0x9f; i++) { exports.handlers.set(i, swapFn); } const logFn = exports.handlers.get(0xa0); for (let i = 0xa1; i <= 0xa4; i++) { exports.handlers.set(i, logFn); } //# sourceMappingURL=functions.js.map