Skip to content

Commit

Permalink
common/vm: add EIP-3855, PUSH0 instruction (#1616)
Browse files Browse the repository at this point in the history
* common/vm: add EIP-3855, PUSH0 instruction

* vm: remove breaking changes from runCode
  • Loading branch information
jochem-brouwer authored Dec 27, 2021
1 parent 0c7bdfc commit 3751bbd
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 1 deletion.
18 changes: 18 additions & 0 deletions packages/common/src/eips/3855.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "EIP-3855",
"number": 3855,
"comment": "PUSH0 instruction",
"url": "https://eips.ethereum.org/EIPS/eip-3855",
"status": "Review",
"minimumHardfork": "chainstart",
"requiredEIPs": [],
"gasConfig": {},
"gasPrices": {
"push0": {
"v": 2,
"d": "Base fee of the PUSH0 opcode"
}
},
"vm": {},
"pow": {}
}
1 change: 1 addition & 0 deletions packages/common/src/eips/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export const EIPs: eipsType = {
3541: require('./3541.json'),
3554: require('./3554.json'),
3675: require('./3675.json'),
3855: require('./3855.json'),
4345: require('./4345.json'),
}
6 changes: 6 additions & 0 deletions packages/vm/src/evm/opcodes/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ const eipOpcodes = [
0x48: { name: 'BASEFEE', isAsync: false },
},
},
{
eip: 3855,
opcodes: {
0x5f: { name: 'PUSH0', isAsync: false },
},
},
]

/**
Expand Down
7 changes: 7 additions & 0 deletions packages/vm/src/evm/opcodes/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,13 @@ export const handlers: Map<number, OpHandler> = new Map([
runState.programCounter = destNum + 1
},
],
// 0x5f: PUSH0
[
0x5f,
function (runState) {
runState.stack.push(new BN(0))
},
],
// 0x60: PUSH
[
0x60,
Expand Down
3 changes: 2 additions & 1 deletion packages/vm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface VMOpts {
* - [EIP-3198](https://eips.ethereum.org/EIPS/eip-3198) - BASEFEE opcode
* - [EIP-3529](https://eips.ethereum.org/EIPS/eip-3529) - Reduction in refunds
* - [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541) - Reject new contracts starting with the 0xEF byte
* - [EIP-3855](https://eips.ethereum.org/EIPS/eip-3855) - PUSH0 instruction
*
* *Annotations:*
*
Expand Down Expand Up @@ -194,7 +195,7 @@ export default class VM extends AsyncEventEmitter {

if (opts.common) {
//EIPs
const supportedEIPs = [1559, 2315, 2537, 2565, 2718, 2929, 2930, 3198, 3529, 3541]
const supportedEIPs = [1559, 2315, 2537, 2565, 2718, 2929, 2930, 3198, 3529, 3541, 3855]
for (const eip of opts.common.eips()) {
if (!supportedEIPs.includes(eip)) {
throw new Error(`${eip} is not supported by the VM`)
Expand Down
87 changes: 87 additions & 0 deletions packages/vm/tests/api/EIPs/eip-3855.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import tape from 'tape'
import VM from '../../../src'
import Common, { Chain, Hardfork } from '@ethereumjs/common'
import { InterpreterStep } from '../../../src/evm/interpreter'
import { BN } from 'ethereumjs-util'
import { ERROR } from '../../../src/exceptions'

tape('EIP 3541 tests', (t) => {
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Chainstart, eips: [3855] })
const commonNoEIP3855 = new Common({
chain: Chain.Mainnet,
hardfork: Hardfork.Chainstart,
eips: [],
})

t.test('should correctly use push0 opcode', async (st) => {
const vm = new VM({ common })
let stack: BN[]

vm.on('step', (e: InterpreterStep) => {
if (stack) {
st.fail('should only do PUSH0 once')
}
stack = e.stack
})

const result = await vm.runCode({
code: Buffer.from('5F', 'hex'),
gasLimit: new BN(10),
})

st.ok(stack!.length == 1)
st.ok(stack![0].eqn(0))
st.ok(result.gasUsed.eqn(common.param('gasPrices', 'push0')))
st.end()
})

t.test('should correctly use push0 to create a stack with stack limit length', async (st) => {
const vm = new VM({ common })
let stack: BN[] = []

vm.on('step', (e: InterpreterStep) => {
stack = e.stack
})

const depth = common.param('vm', 'stackLimit')

const result = await vm.runCode({
code: Buffer.from('5F'.repeat(depth), 'hex'),
gasLimit: new BN(10000),
})

st.ok(stack.length == depth)
stack.forEach((elem: BN) => {
if (!elem.eqn(0)) {
st.fail('stack element is not 0')
}
})
st.ok(result.gasUsed.eqn(common.param('gasPrices', 'push0') * depth))
st.end()
})

t.test('should correctly use push0 to create a stack with stack limit + 1 length', async (st) => {
const vm = new VM({ common })

const depth = <number>common.param('vm', 'stackLimit') + 1

const result = await vm.runCode({
code: Buffer.from('5F'.repeat(depth), 'hex'),
gasLimit: new BN(10000),
})

st.ok(result.exceptionError?.error === ERROR.STACK_OVERFLOW)
st.end()
})

t.test('push0 is not available if EIP3855 is not activated', async (st) => {
const vm = new VM({ common: commonNoEIP3855 })

const result = await vm.runCode({
code: Buffer.from('5F', 'hex'),
gasLimit: new BN(10000),
})

st.ok(result.exceptionError!.error === ERROR.INVALID_OPCODE)
})
})

0 comments on commit 3751bbd

Please sign in to comment.