-
Notifications
You must be signed in to change notification settings - Fork 828
Istanbul: EIP-2200 net gas metering for SSTORE #590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
f28c552
9a73667
c969e59
28abb65
45de15c
d6fac6e
0264f70
789c8ed
eb68617
d6a7e84
f2215c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const tape = require('tape') | ||
const BN = require('bn.js') | ||
const Common = require('ethereumjs-common').default | ||
const VM = require('../../../dist/index').default | ||
const PStateManager = require('../../../dist/state/promisified').default | ||
const { ERROR } = require('../../../dist/exceptions') | ||
const { createAccount } = require('../utils') | ||
|
||
const testCases = [ | ||
{ original: new BN(0), code: '60006000556000600055', used: 1612, refund: 0 }, // 0 -> 0 -> 0 | ||
{ original: new BN(0), code: '60006000556001600055', used: 20812, refund: 0 }, // 0 -> 0 -> 1 | ||
{ original: new BN(0), code: '60016000556000600055', used: 20812, refund: 19200 }, // 0 -> 1 -> 0 | ||
{ original: new BN(0), code: '60016000556002600055', used: 20812, refund: 0 }, // 0 -> 1 -> 2 | ||
{ original: new BN(0), code: '60016000556001600055', used: 20812, refund: 0 }, // 0 -> 1 -> 1 | ||
{ original: new BN(1), code: '60006000556000600055', used: 5812, refund: 15000 }, // 1 -> 0 -> 0 | ||
{ original: new BN(1), code: '60006000556001600055', used: 5812, refund: 4200 }, // 1 -> 0 -> 1 | ||
{ original: new BN(1), code: '60006000556002600055', used: 5812, refund: 0 }, // 1 -> 0 -> 2 | ||
{ original: new BN(1), code: '60026000556000600055', used: 5812, refund: 15000 }, // 1 -> 2 -> 0 | ||
{ original: new BN(1), code: '60026000556003600055', used: 5812, refund: 0 }, // 1 -> 2 -> 3 | ||
{ original: new BN(1), code: '60026000556001600055', used: 5812, refund: 4200 }, // 1 -> 2 -> 1 | ||
{ original: new BN(1), code: '60026000556002600055', used: 5812, refund: 0 }, // 1 -> 2 -> 2 | ||
{ original: new BN(1), code: '60016000556000600055', used: 5812, refund: 15000 }, // 1 -> 1 -> 0 | ||
{ original: new BN(1), code: '60016000556002600055', used: 5812, refund: 0 }, // 1 -> 1 -> 2 | ||
{ original: new BN(1), code: '60016000556001600055', used: 1612, refund: 0 }, // 1 -> 1 -> 1 | ||
{ original: new BN(0), code: '600160005560006000556001600055', used: 40818, refund: 19200 }, // 0 -> 1 -> 0 -> 1 | ||
{ original: new BN(1), code: '600060005560016000556000600055', used: 10818, refund: 19200 }, // 1 -> 0 -> 1 -> 0 | ||
{ original: new BN(1), gas: new BN(2306), code: '6001600055', used: 2306, refund: 0, err: ERROR.OUT_OF_GAS }, // 1 -> 1 (2300 sentry + 2xPUSH) | ||
{ original: new BN(1), gas: new BN(2307), code: '6001600055', used: 806, refund: 0 } // 1 -> 1 (2301 sentry + 2xPUSH) | ||
] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, the numbers in the test cases differ to what is listed in the EIP? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, these test cases have been added after I created the PR: ethereum/EIPs@01b66af It seems the EIP document has also been modified. Will have to look into it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The parameters in the EIP are also named very much differently than here (and in Go), did this also change? Or is this an intentional deviation to be in line with the old Constantinople naming? If this changed we should likely do the extra round sigh on the Common library and change the parameter names (and eventually delete some?). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the test vectors that were recently added to the EIP are for an older version of the EIP which assumed cost of SLOAD to be 200 instead of 800. See comment: ethereum/EIPs#2200 (comment) About the param names, as long as we're conforming to test cases it should be fine. I don't think every client uses the same param names. The EIP is also somewhat under-specified. I'm more confident in geth's code as that's what eventually makes it into mainnet. But we can wait until the EIP's PR is merged, hopefully by then things will be more clear. |
||
|
||
tape('Istanbul: EIP-2200: net-metering SSTORE', async (t) => { | ||
const caller = Buffer.from('0000000000000000000000000000000000000000', 'hex') | ||
const addr = Buffer.from('00000000000000000000000000000000000000ff', 'hex') | ||
const key = new BN(0).toArrayLike(Buffer, 'be', 32) | ||
for (const testCase of testCases) { | ||
const common = new Common('mainnet', 'istanbul') | ||
const vm = new VM({ common }) | ||
const state = new PStateManager(vm.stateManager) | ||
|
||
const account = createAccount('00', '00') | ||
await state.putAccount(addr, account) | ||
await state.putContractCode(addr, Buffer.from(testCase.code, 'hex')) | ||
if (!testCase.original.isZero()) { | ||
await state.putContractStorage(addr, key, testCase.original) | ||
} | ||
|
||
const runCallArgs = { | ||
caller, | ||
gasLimit: testCase.gas ? testCase.gas : new BN(0xffffffffff), | ||
to: addr | ||
} | ||
|
||
try { | ||
const res = await vm.runCall(runCallArgs) | ||
if (testCase.err) { | ||
t.equal(res.execResult.exceptionError.error, testCase.err) | ||
} else { | ||
t.assert(res.execResult.exceptionError === undefined) | ||
} | ||
t.assert(new BN(testCase.used).eq(res.gasUsed)) | ||
t.assert(new BN(testCase.refund).eq(res.execResult.gasRefund)) | ||
} catch (e) { | ||
t.fail(e.message) | ||
} | ||
} | ||
|
||
t.end() | ||
}) |
Uh oh!
There was an error while loading. Please reload this page.