diff --git a/lib/__tests__/integration.spec.ts b/lib/__tests__/integration.spec.ts index 0c1bae9..5cfb5a0 100644 --- a/lib/__tests__/integration.spec.ts +++ b/lib/__tests__/integration.spec.ts @@ -11,7 +11,7 @@ import { describe("EMV-TS", () => { it("should work", () => compareWithReferentialImpl("60606040523415600e")); - it.skip("should work with more complicated bytecode", () => { + it("should work with more complicated bytecode", () => { const bin = fs.readFileSync(join(__dirname, "./contracts/DumbContract.bin"), "utf-8"); const abi = JSON.parse(fs.readFileSync(join(__dirname, "./contracts/DumbContract.abi"), "utf-8")); const contract = web3.eth.contract(abi).at("0x0"); diff --git a/lib/opcodes/__tests__/arithmetic.spec.ts b/lib/opcodes/__tests__/arithmetic.spec.ts index 96700cf..d8dfdde 100644 --- a/lib/opcodes/__tests__/arithmetic.spec.ts +++ b/lib/opcodes/__tests__/arithmetic.spec.ts @@ -15,6 +15,15 @@ describe("arithmetic opcodes", () => { )); }); + describe("SUB", () => { + it("SUB with overflow", () => + compareWithReferentialImpl( + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03", + )); + + it.skip("SUB with minus sign"); + }); + describe("DIV", () => { it("div with overflow", () => compareWithReferentialImpl( diff --git a/lib/opcodes/__tests__/memory.spec.ts b/lib/opcodes/__tests__/memory.spec.ts index 3cb04d2..2090da8 100644 --- a/lib/opcodes/__tests__/memory.spec.ts +++ b/lib/opcodes/__tests__/memory.spec.ts @@ -7,4 +7,8 @@ describe("memory opcodes", () => { it("with more than 1 word size data", () => compareWithReferentialImpl("7f4e616d655265670000000000000000f0000b0000000000000000000000000000606052")); }); + + describe("MLOAD", () => { + it("simple", () => compareWithReferentialImpl("6060600052600051")); + }); }); diff --git a/lib/opcodes/arithmetic.ts b/lib/opcodes/arithmetic.ts index e5c9a03..737c053 100644 --- a/lib/opcodes/arithmetic.ts +++ b/lib/opcodes/arithmetic.ts @@ -1,4 +1,4 @@ -import { Opcode, notImplementedError } from "./common"; +import { Opcode } from "./common"; import { IMachineState } from "../VM"; import { MAX_UINT_256 } from "../utils/bytes"; import { BN } from "bn.js"; @@ -37,8 +37,14 @@ export class SubOpcode extends Opcode { static id = 0x03; static type = "SUB"; - run(_state: IMachineState): void { - notImplementedError(); + run(state: IMachineState): void { + const arg1 = state.stack.pop(); + const arg2 = state.stack.pop(); + + const result = arg1.sub(arg2).mod(MAX_UINT_256); + + state.pc += 1; + state.stack.push(result); } } diff --git a/lib/opcodes/memory.ts b/lib/opcodes/memory.ts index ed8eae0..134fe9d 100644 --- a/lib/opcodes/memory.ts +++ b/lib/opcodes/memory.ts @@ -1,6 +1,7 @@ import { IMachineState, IEnvironment } from "../VM"; -import { Opcode, notImplementedError } from "./common"; +import { Opcode } from "./common"; import { arrayCopy } from "../utils/arrays"; +import { BN } from "bn.js"; /** * Stores full word in memory. @@ -29,8 +30,14 @@ export class MLoadOpcode extends Opcode { static id = 0x51; static type = "MLOAD"; - run(_state: IMachineState): void { - notImplementedError(); + run(state: IMachineState): void { + const address = state.stack.pop().toNumber(); + const valueRaw = state.memory.slice(address, address + 32); + + const value = new BN(valueRaw, undefined, "be"); + + state.stack.push(value); + state.pc += 1; } }