UNPKG

@polygon-hermez/vm

Version:
1,305 lines 64 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handlers = void 0; var ethereumjs_util_1 = require("ethereumjs-util"); var util_1 = require("./util"); var exceptions_1 = require("../../exceptions"); var smtUtils = require('@polygon-hermez/zkevm-commonjs').smtUtils; // 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(3), 3), a = _a[0], b = _a[1], c = _a[2]; var 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, }); var _a = __read(runState.stack.popN(3), 3), a = _a[0], b = _a[1], c = _a[2]; var 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) { var _a = __read(runState.stack.popN(2), 2), base = _a[0], exponent = _a[1]; 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; } var byteLength = exponent.byteLength(); if (byteLength < 1 || byteLength > 32) { (0, util_1.trap)(exceptions_1.ERROR.OUT_OF_RANGE); } var gasPrice = common.param('gasPrices', 'expByte'); var 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; } var m = ethereumjs_util_1.BN.red(ethereumjs_util_1.TWO_POW256); var redBase = base.toRed(m); var 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 */ var _a = __read(runState.stack.popN(2), 2), k = _a[0], val = _a[1]; if (k.ltn(31)) { var signBit = k.muln(8).iaddn(7).toNumber(); var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var a = runState.stack.pop(); var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var 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, }); var a = runState.stack.pop(); var 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, }); var _a = __read(runState.stack.popN(2), 2), pos = _a[0], word = _a[1]; if (pos.gten(32)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; if (a.gten(256)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; if (a.gten(256)) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } var 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, }); var _a = __read(runState.stack.popN(2), 2), a = _a[0], b = _a[1]; var r; var 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; } var c = b.shrn(a.toNumber()); if (isSigned) { var shiftedOutWidth = 255 - a.toNumber(); var 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) { var _a = __read(runState.stack.popN(2), 2), offset = _a[0], length = _a[1]; runState.vcm.computeFunctionCounters('opSha3', { inputSize: length.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); var data = Buffer.alloc(0); if (!length.isZero()) { data = runState.memory.read(offset.toNumber(), length.toNumber()); } var 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, }); var address = new ethereumjs_util_1.BN(runState.eei.getAddress().buf); runState.stack.push(address); }, ], // 0x31: BALANCE [ 0x31, function (runState) { return __awaiter(this, void 0, void 0, function () { var addressBN, address, balance; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opBalance', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); addressBN = runState.stack.pop(); address = new ethereumjs_util_1.Address((0, util_1.addressToBuffer)(addressBN)); return [4 /*yield*/, runState.eei.getExternalBalance(address)]; case 1: balance = _a.sent(); runState.stack.push(balance); return [2 /*return*/]; } }); }); }, ], // 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, }); var pos = runState.stack.pop(); if (pos.gt(runState.eei.getCallDataSize())) { runState.stack.push(new ethereumjs_util_1.BN(0)); return; } var i = pos.toNumber(); var loaded = runState.eei.getCallData().slice(i, i + 32); loaded = loaded.length ? loaded : Buffer.from([0]); var 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, }); var r = runState.eei.getCallDataSize(); runState.stack.push(r); }, ], // 0x37: CALLDATACOPY [ 0x37, function (runState) { var _a = __read(runState.stack.popN(3), 3), memOffset = _a[0], dataOffset = _a[1], dataLength = _a[2]; if (!dataLength.eqn(0)) { var 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, }); var memOffsetNum = memOffset.toNumber(); var 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) { var _a = __read(runState.stack.popN(3), 3), memOffset = _a[0], codeOffset = _a[1], dataLength = _a[2]; if (!dataLength.eqn(0)) { var 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, }); var memOffsetNum = memOffset.toNumber(); var lengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, lengthNum); runState.memory.write(memOffsetNum, lengthNum, data); } }, ], // 0x3b: EXTCODESIZE [ 0x3b, function (runState) { return __awaiter(this, void 0, void 0, function () { var addressBN, size; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opExtCodeSize', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); addressBN = runState.stack.pop(); return [4 /*yield*/, runState.eei.getExternalCodeSize(addressBN)]; case 1: size = _a.sent(); runState.stack.push(size); return [2 /*return*/]; } }); }); }, ], // 0x3c: EXTCODECOPY [ 0x3c, function (runState) { return __awaiter(this, void 0, void 0, function () { var _a, addressBN, memOffset, codeOffset, dataLength, code, data, memOffsetNum, lengthNum; return __generator(this, function (_b) { switch (_b.label) { case 0: _a = __read(runState.stack.popN(4), 4), addressBN = _a[0], memOffset = _a[1], codeOffset = _a[2], dataLength = _a[3]; if (!!dataLength.eqn(0)) return [3 /*break*/, 2]; return [4 /*yield*/, runState.eei.getExternalCode(addressBN)]; case 1: code = _b.sent(); 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, }); memOffsetNum = memOffset.toNumber(); lengthNum = dataLength.toNumber(); runState.memory.extend(memOffsetNum, lengthNum); runState.memory.write(memOffsetNum, lengthNum, data); _b.label = 2; case 2: return [2 /*return*/]; } }); }); }, ], // 0x3f: EXTCODEHASH [ 0x3f, function (runState) { return __awaiter(this, void 0, void 0, function () { var addressBN, code, lpCode; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opExtCodeHash', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); addressBN = runState.stack.pop(); return [4 /*yield*/, runState.eei.getExternalCode(addressBN)]; case 1: code = _a.sent(); if (code.length === 0) { runState.stack.push(new ethereumjs_util_1.BN(0)); return [2 /*return*/]; } return [4 /*yield*/, smtUtils.hashContractBytecode(code.toString('hex'))]; case 2: lpCode = _a.sent(); runState.stack.push(new ethereumjs_util_1.BN(lpCode.slice(2), 16)); return [2 /*return*/]; } }); }); }, ], // 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) { var _a = __read(runState.stack.popN(3), 3), memOffset = _a[0], returnDataOffset = _a[1], dataLength = _a[2]; if (!dataLength.eqn(0)) { var 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, }); var memOffsetNum = memOffset.toNumber(); var 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, function (runState) { return __awaiter(this, void 0, void 0, function () { var number, hash; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opBlockHash', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); number = runState.stack.pop(); return [4 /*yield*/, runState.eei.getBatchHash(number)]; case 1: hash = _a.sent(); runState.stack.push(hash); return [2 /*return*/]; } }); }); }, ], // 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, function (runState) { return __awaiter(this, void 0, void 0, function () { var num; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opNumber', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); return [4 /*yield*/, runState.eei.getBlockNum()]; case 1: num = _a.sent(); runState.stack.push(num); return [2 /*return*/]; } }); }); }, ], // 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, }); var pos = runState.stack.pop(); var 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, }); var _a = __read(runState.stack.popN(2), 2), offset = _a[0], word = _a[1]; var buf = word.toArrayLike(Buffer, 'be', 32); var 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, }); var _a = __read(runState.stack.popN(2), 2), offset = _a[0], byte = _a[1]; // 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 var buf = Buffer.from([byte.andln(0xff)]); var offsetNum = offset.toNumber(); runState.memory.extend(offsetNum, 1); runState.memory.write(offsetNum, 1, buf); }, ], // 0x54: SLOAD [ 0x54, function (runState) { return __awaiter(this, void 0, void 0, function () { var key, keyBuf, value, valueBN; return __generator(this, function (_a) { switch (_a.label) { case 0: runState.vcm.computeFunctionCounters('opSLoad', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); key = runState.stack.pop(); keyBuf = key.toArrayLike(Buffer, 'be', 32); return [4 /*yield*/, runState.eei.storageLoad(keyBuf)]; case 1: value = _a.sent(); valueBN = value.length ? new ethereumjs_util_1.BN(value) : new ethereumjs_util_1.BN(0); runState.stack.push(valueBN); return [2 /*return*/]; } }); }); }, ], // 0x55: SSTORE [ 0x55, function (runState) { return __awaiter(this, void 0, void 0, function () { var _a, key, val, keyBuf, value; return __generator(this, function (_b) { switch (_b.label) { case 0: runState.vcm.computeFunctionCounters('opSStore', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); _a = __read(runState.stack.popN(2), 2), key = _a[0], val = _a[1]; keyBuf = key.toArrayLike(Buffer, 'be', 32); if (val.isZero()) { value = Buffer.from([]); } else { value = val.toArrayLike(Buffer, 'be'); } return [4 /*yield*/, runState.eei.storageStore(keyBuf, value)]; case 1: _b.sent(); return [2 /*return*/]; } }); }); }, ], // 0x56: JUMP [ 0x56, function (runState) { runState.vcm.computeFunctionCounters('opJump', { isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); var 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)); } var 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, }); var _a = __read(runState.stack.popN(2), 2), dest = _a[0], cond = _a[1]; if (!cond.isZero()) { if (dest.gt(runState.eei.getCodeSize())) { (0, util_1.trap)(exceptions_1.ERROR.INVALID_JUMP + ' at ' + (0, util_1.describeLocation)(runState)); } var 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); } var dest = runState.returnStack.pop(); runState.programCounter = dest.toNumber(); }, ], // 0x5e: JUMPSUB [ 0x5e, function (runState) { var 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)); } var 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) { var numToPush = runState.opCode - 0x5f; runState.vcm.computeFunctionCounters('_opPush', { pushBytes: numToPush, isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); var 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, }); var 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, }); var stackPos = runState.opCode - 0x8f; runState.stack.swap(stackPos); }, ], // 0xa0: LOG [ 0xa0, function (runState) { var _a = __read(runState.stack.popN(2), 2), memOffset = _a[0], memLength = _a[1]; runState.vcm.computeFunctionCounters('_opLog', { inputSize: memLength.toNumber(), isCreate: runState.eei._env.isCreate, isDeploy: runState.eei._env.isDeploy, }); var topicsCount = runState.opCode - 0xa0; var topics = runState.stack.popN(topicsCount); var topicsBuf = topics.map(function (a) { return a.toArrayLike(Buffer, 'be', 32); }); var 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, function (runState) { return __awaiter(this, void 0, void 0, function () { var _a, value, offset, length, gasLimit, data, ret; return __generator(this, function (_b) { switch (_b.label) { case 0: _a = __read(runState.stack.popN(3), 3), value = _a[0], offset = _a[1], length = _a[2]; 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(), }); gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; data = Buffer.alloc(0); if (!length.isZero()) { data = runState.memory.read(offset.toNumber(), length.toNumber()); } return [4 /*yield*/, runState.eei.create(gasLimit, value, data)]; case 1: ret = _b.sent(); 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 [2 /*return*/, ret.results]; } }); }); }, ], // 0xf5: CREATE2 [ 0xf5, function (runState) { return __awaiter(this, void 0, void 0, function () { var _a, value, offset, length, salt, gasLimit, data, ret; return __generator(this, function (_b) { switch (_b.label) { case 0: if (runState.eei.isStatic()) { (0, util_1.trap)(exceptions_1.ERROR.STATIC_STATE_CHANGE); } _a = __read(runState.stack.popN(4), 4), value = _a[0], offset = _a[1], length = _a[2], salt = _a[3]; 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, }); gasLimit = runState.messageGasLimit; runState.messageGasLimit = undefined; data = Buffer.alloc(0); i