Skip to content

Commit

Permalink
Support for fork definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
acuarica committed Dec 24, 2023
1 parent 8b06db0 commit 209718e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 13 deletions.
69 changes: 59 additions & 10 deletions src/step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,64 @@ function Step<
}

/**
* This module is used to `decode` bytecode into `Opcode`.
*
* https://ethereum.github.io/execution-specs/diffs/paris_shanghai.html
* https://eips.ethereum.org/EIPS/eip-3855
* Latest fork definition.
*/
export const STEP = Shanghai;

/**
* Defines the `Shanghai` hardfork.
* It includes the `PUSH0` instruction.
*
* https://ethereum.github.io/execution-specs/diffs/gray_glacier_paris.html
* https://eips.ethereum.org/EIPS/eip-4399
* Solidity `0.8.20` uses `push0` for placing `0` on the Stack.
* This decreases the deployment and runtime costs.
*
* @see https://ethereum.github.io/execution-specs/diffs/paris_shanghai.html
* @see https://eips.ethereum.org/EIPS/eip-3855
* @see https://soliditylang.org/blog/2023/05/10/solidity-0.8.20-release-announcement/
*/
export function STEP(
export function Shanghai(
events: IEvents = {},
variables: IStore['variables'] = {},
mappings: IStore['mappings'] = {},
functionBranches: ISelectorBranches = new Map(),
) {
return Object.assign(
Paris(events, variables, mappings, functionBranches),
Step({
PUSH0: [0x5f, ({ stack }: Operand<Expr>) => stack.push(new Val(0n, true))]
})
);
}

/**
* Defines the `Paris` hardfork.
* It includes the `PREVRANDAO` instruction.
*
* Solidity `0.8.18` includes _Support for Paris Hardfork_,
* which introduces the global `block.prevrandao` built-in in Solidity and `prevrandao()`
* instruction in inline assembly for EVM versions >= Paris.
*
* @see https://ethereum.github.io/execution-specs/diffs/gray_glacier_paris.html
* @see https://eips.ethereum.org/EIPS/eip-4399
* @see https://soliditylang.org/blog/2023/02/01/solidity-0.8.18-release-announcement
*/
export function Paris(
events: IEvents = {},
variables: IStore['variables'] = {},
mappings: IStore['mappings'] = {},
functionBranches: ISelectorBranches = new Map(),
) {
return Object.assign(
London(events, variables, mappings, functionBranches),
Step({
PREVRANDAO: [0x44, function prevrandao({ stack }: Operand<Expr>) {
stack.push(Props['block.prevrandao']);
}],
})
);
}

export function London(
events: IEvents = {},
variables: IStore['variables'] = {},
mappings: IStore['mappings'] = {},
Expand All @@ -156,9 +205,6 @@ export function STEP(
LOGS(events),
STORAGE({ variables, mappings }),
FLOW(functionBranches),
Step({
PUSH0: [0x5f, ({ stack }) => stack.push(new Val(0n))]
})
);
}

Expand All @@ -167,6 +213,9 @@ export function STEP(
*/
export type Mnemonic<T> = { [k in keyof T]: T[k] extends StepFn ? (k & string) : never }[keyof T];

/**
* This module is used to `decode` bytecode into `Opcode`.
*/
class Undef {

/**
Expand Down
7 changes: 5 additions & 2 deletions test/evm/special.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';

import { EVM, State, reduce } from 'sevm';
import { EVM, London, Shanghai, State, reduce } from 'sevm';
import type { Expr, Inst, Log } from 'sevm/ast';
import { Props } from 'sevm/ast';

Expand All @@ -23,7 +23,9 @@ describe('evm::special', function () {
fallback() external payable { emit Deposit(${prop.symbol}); }
}`;

const evm = new EVM(compile(src, '0.8.16', this).bytecode);
const evm = name === 'block.difficulty'
? new EVM(compile(src, '0.8.16', this).bytecode, London())
: new EVM(compile(src, '0.8.21', this).bytecode, Shanghai());
let state = new State<Inst, Expr>();
evm.run(0, state);

Expand All @@ -32,6 +34,7 @@ describe('evm::special', function () {
}

const stmts = reduce(state.stmts);
console.log(stmts);
const stmt = stmts[0];
expect(stmt.name).to.be.equal('Log');
expect((<Log>stmt).args![0].eval()).to.be.deep.equal(prop);
Expand Down
26 changes: 25 additions & 1 deletion test/step.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';

import { Opcode, type Operand, sol, Stack, State, STEP } from 'sevm';
import { Opcode, type Operand, sol, Stack, State, STEP, London, Paris } from 'sevm';
import { Val, type Expr, Local, Locali, type Inst, Invalid, MStore, Jump, Branch, Jumpi, Log, type IEvents, Props } from 'sevm/ast';
import { Add, Create, MLoad, Return, SelfDestruct, Sha3, Stop } from 'sevm/ast';
import { $exprs } from './$exprs';
Expand Down Expand Up @@ -491,4 +491,28 @@ describe('::step', function () {
});
});

describe('London -> Paris upgrade', function () {
it('should decode `0x44` -> `DIFFICULTY` with London', function () {
const step = London();

const [, , mnemonic] = step[0x44] as [unknown, unknown, 'DIFFICULTY'];
expect(mnemonic).to.be.deep.equal('DIFFICULTY');

const stack = new Stack<Expr>();
step[mnemonic]({ stack });
expect(stack.top).to.be.equal(Props['block.difficulty']);
});

it('should decode `0x44` -> `PREVRANDAO` with Paris', function () {
const step = Paris();

const [, , mnemonic] = step[0x44] as [unknown, unknown, 'PREVRANDAO'];
expect(mnemonic).to.be.deep.equal('PREVRANDAO');

const stack = new Stack<Expr>();
step[mnemonic]({ stack });
expect(stack.top).to.be.equal(Props['block.prevrandao']);
});

});
});

0 comments on commit 209718e

Please sign in to comment.