diff --git a/lib/opFns.js b/lib/opFns.js index 8d0c95fc67..611e8c6368 100644 --- a/lib/opFns.js +++ b/lib/opFns.js @@ -157,6 +157,45 @@ module.exports = { return new BN(word.shrn((31 - pos.toNumber()) * 8).andln(0xff)) }, + SHL: function (a, b, runState) { + if (!runState._common.gteHardfork('constantinople')) { + trap(ERROR.INVALID_OPCODE) + } + if (a.gten(256)) { + return new BN(0) + } + return b.shln(a.toNumber()).iand(utils.MAX_INTEGER) + }, + SHR: function (a, b, runState) { + if (!runState._common.gteHardfork('constantinople')) { + trap(ERROR.INVALID_OPCODE) + } + if (a.gten(256)) { + return new BN(0) + } + return b.shrn(a.toNumber()) + }, + SAR: function (a, b, runState) { + if (!runState._common.gteHardfork('constantinople')) { + trap(ERROR.INVALID_OPCODE) + } + const isSigned = b.testn(255) + if (a.gten(256)) { + if (isSigned) { + return new BN(utils.MAX_INTEGER) + } else { + return new BN(0) + } + } + const c = b.shrn(a.toNumber()) + if (isSigned) { + const shiftedOutWidth = 255 - a.toNumber() + const mask = utils.MAX_INTEGER.shrn(shiftedOutWidth).shln(shiftedOutWidth) + return c.ior(mask) + } else { + return c + } + }, // 0x20 range - crypto SHA3: function (offset, length, runState) { var data = memLoad(runState, offset, length) diff --git a/lib/opcodes.js b/lib/opcodes.js index f277001e13..11dbc31d9f 100644 --- a/lib/opcodes.js +++ b/lib/opcodes.js @@ -26,6 +26,9 @@ const codes = { 0x18: ['XOR', 3, 2, 1, false], 0x19: ['NOT', 3, 1, 1, false], 0x1a: ['BYTE', 3, 2, 1, false], + 0x1b: ['SHL', 3, 2, 1, false], + 0x1c: ['SHR', 3, 2, 1, false], + 0x1d: ['SAR', 3, 2, 1, false], // 0x20 range - crypto 0x20: ['SHA3', 30, 2, 1, false], diff --git a/lib/runCode.js b/lib/runCode.js index 7dace81894..921342af1d 100644 --- a/lib/runCode.js +++ b/lib/runCode.js @@ -213,14 +213,14 @@ module.exports = function (opts, cb) { if (result !== undefined) { if (retNum !== 1) { // opcode post-stack mismatch - return cb(VmError(ERROR.INTERNAL_ERROR)) + return cb(new VmError(ERROR.INTERNAL_ERROR)) } runState.stack.push(result) } else { if (!opInfo.async && retNum !== 0) { // opcode post-stack mismatch - return cb(VmError(ERROR.INTERNAL_ERROR)) + return cb(new VmError(ERROR.INTERNAL_ERROR)) } }