-
Notifications
You must be signed in to change notification settings - Fork 790
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
Fix EIP2929 #1124
Fix EIP2929 #1124
Changes from 1 commit
bdf73e7
acd608c
212f4cd
2eeddab
3d9dcbc
dfadddf
b40432b
488d392
99c0253
f4bdf9b
37d6c8c
f8fed0c
dc3d90d
e34982a
0826286
715fcb1
5772bf5
21faebc
2e7c765
231b071
d67e8bd
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 |
---|---|---|
|
@@ -10,7 +10,12 @@ import { RunState } from './../interpreter' | |
* @param {RunState} runState | ||
* @param {BN} address | ||
*/ | ||
export function accessAddressEIP2929(runState: RunState, address: Address, baseFee?: number) { | ||
export function accessAddressEIP2929( | ||
runState: RunState, | ||
address: Address, | ||
chargeGas = true, | ||
isSelfdestruct = false | ||
) { | ||
if (!runState._common.isActivatedEIP(2929)) return | ||
|
||
const addressStr = address.buf | ||
|
@@ -22,16 +27,16 @@ export function accessAddressEIP2929(runState: RunState, address: Address, baseF | |
|
||
// CREATE, CREATE2 opcodes have the address warmed for free. | ||
// selfdestruct beneficiary address reads are charged an *additional* cold access | ||
if (baseFee !== undefined) { | ||
if (chargeGas) { | ||
runState.eei.useGas( | ||
new BN(runState._common.param('gasPrices', 'coldaccountaccess') - baseFee), | ||
new BN(runState._common.param('gasPrices', 'coldaccountaccess')), | ||
'EIP-2929 -> coldaccountaccess' | ||
) | ||
} | ||
// Warm: (selfdestruct beneficiary address reads are not charged when warm) | ||
} else if (baseFee !== undefined && baseFee > 0) { | ||
} else if (chargeGas && !isSelfdestruct) { | ||
runState.eei.useGas( | ||
new BN(runState._common.param('gasPrices', 'warmstorageread') - baseFee), | ||
new BN(runState._common.param('gasPrices', 'warmstorageread')), | ||
'EIP-2929 -> warmstorageread' | ||
) | ||
} | ||
|
@@ -47,7 +52,6 @@ export function accessAddressEIP2929(runState: RunState, address: Address, baseF | |
export function accessStorageEIP2929(runState: RunState, key: Buffer, isSstore: boolean) { | ||
if (!runState._common.isActivatedEIP(2929)) return | ||
|
||
const baseFee = !isSstore ? runState._common.param('gasPrices', 'sload') : 0 | ||
const address = runState.eei.getAddress().buf | ||
|
||
const slotIsCold = !(<EIP2929StateManager>runState.stateManager).isWarmedStorage(address, key) | ||
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. Nice and thought-through solution, cool! 👍 |
||
|
@@ -57,12 +61,12 @@ export function accessStorageEIP2929(runState: RunState, key: Buffer, isSstore: | |
// eslint-disable-next-line prettier/prettier | ||
(<EIP2929StateManager>runState.stateManager).addWarmedStorage(address, key) | ||
runState.eei.useGas( | ||
new BN(runState._common.param('gasPrices', 'coldsload') - baseFee), | ||
new BN(runState._common.param('gasPrices', 'coldsload')), | ||
'EIP-2929 -> coldsload' | ||
) | ||
} else if (!isSstore) { | ||
runState.eei.useGas( | ||
new BN(runState._common.param('gasPrices', 'warmstorageread') - baseFee), | ||
new BN(runState._common.param('gasPrices', 'warmstorageread')), | ||
'EIP-2929 -> warmstorageread' | ||
) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -411,7 +411,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
async function (runState: RunState) { | ||
const addressBN = runState.stack.pop() | ||
const address = new Address(addressToBuffer(addressBN)) | ||
accessAddressEIP2929(runState, address, runState._common.param('gasPrices', 'balance')) | ||
accessAddressEIP2929(runState, address) | ||
const balance = await runState.eei.getExternalBalance(address) | ||
runState.stack.push(balance) | ||
}, | ||
|
@@ -514,7 +514,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
async function (runState: RunState) { | ||
const addressBN = runState.stack.pop() | ||
const address = new Address(addressToBuffer(addressBN)) | ||
accessAddressEIP2929(runState, address, runState._common.param('gasPrices', 'extcodesize')) | ||
accessAddressEIP2929(runState, address) | ||
const size = await runState.eei.getExternalCodeSize(addressBN) | ||
runState.stack.push(size) | ||
}, | ||
|
@@ -528,7 +528,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
// FIXME: for some reason this must come before subGas | ||
subMemUsage(runState, memOffset, length) | ||
const address = new Address(addressToBuffer(addressBN)) | ||
accessAddressEIP2929(runState, address, runState._common.param('gasPrices', 'extcodecopy')) | ||
accessAddressEIP2929(runState, address) | ||
// copy fee | ||
runState.eei.useGas( | ||
new BN(runState._common.param('gasPrices', 'copy')).imul(divCeil(length, new BN(32))), | ||
|
@@ -550,7 +550,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
async function (runState: RunState) { | ||
const addressBN = runState.stack.pop() | ||
const address = new Address(addressToBuffer(addressBN)) | ||
accessAddressEIP2929(runState, address, runState._common.param('gasPrices', 'extcodehash')) | ||
accessAddressEIP2929(runState, address) | ||
const empty = await runState.eei.isAccountEmpty(address) | ||
if (empty) { | ||
runState.stack.push(new BN(0)) | ||
|
@@ -940,6 +940,8 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
|
||
const [value, offset, length] = runState.stack.popN(3) | ||
|
||
accessAddressEIP2929(runState, runState.eei.getAddress(), false) | ||
|
||
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. Just as some post-review question: is the order with 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. Good question, and also a bit sloppy of me. But I just explicitly checked; the memory gas cost is deterministic and does not depend on the current gas available, so the order does not matter. I don't really want to trigger a new CI run, so I will merge here. |
||
subMemUsage(runState, offset, length) | ||
let gasLimit = new BN(runState.eei.getGasLeft()) | ||
gasLimit = maxCallGas(gasLimit, runState.eei.getGasLeft(), runState) | ||
|
@@ -949,7 +951,6 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
data = runState.memory.read(offset.toNumber(), length.toNumber()) | ||
} | ||
|
||
accessAddressEIP2929(runState, runState.eei.getAddress()) | ||
const ret = await runState.eei.create(gasLimit, value, data) | ||
runState.stack.push(ret) | ||
}, | ||
|
@@ -965,7 +966,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
const [value, offset, length, salt] = runState.stack.popN(4) | ||
|
||
subMemUsage(runState, offset, length) | ||
accessAddressEIP2929(runState, runState.eei.getAddress()) | ||
accessAddressEIP2929(runState, runState.eei.getAddress(), false) | ||
|
||
// Deduct gas costs for hashing | ||
runState.eei.useGas( | ||
|
@@ -1009,7 +1010,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
} | ||
subMemUsage(runState, inOffset, inLength) | ||
subMemUsage(runState, outOffset, outLength) | ||
accessAddressEIP2929(runState, toAddress, runState._common.param('gasPrices', 'call')) | ||
accessAddressEIP2929(runState, toAddress) | ||
|
||
if (!value.isZero()) { | ||
runState.eei.useGas( | ||
|
@@ -1076,7 +1077,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
|
||
subMemUsage(runState, inOffset, inLength) | ||
subMemUsage(runState, outOffset, outLength) | ||
accessAddressEIP2929(runState, toAddress, runState._common.param('gasPrices', 'callcode')) | ||
accessAddressEIP2929(runState, toAddress) | ||
|
||
if (!value.isZero()) { | ||
runState.eei.useGas( | ||
|
@@ -1123,7 +1124,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
|
||
subMemUsage(runState, inOffset, inLength) | ||
subMemUsage(runState, outOffset, outLength) | ||
accessAddressEIP2929(runState, toAddress, runState._common.param('gasPrices', 'delegatecall')) | ||
accessAddressEIP2929(runState, toAddress) | ||
const gasLimit = maxCallGas(currentGasLimit, runState.eei.getGasLeft(), runState) | ||
// note that TangerineWhistle or later this cannot happen (it could have ran out of gas prior to getting here though) | ||
if (gasLimit.gt(runState.eei.getGasLeft())) { | ||
|
@@ -1158,7 +1159,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
|
||
subMemUsage(runState, inOffset, inLength) | ||
subMemUsage(runState, outOffset, outLength) | ||
accessAddressEIP2929(runState, toAddress, runState._common.param('gasPrices', 'staticcall')) | ||
accessAddressEIP2929(runState, toAddress) | ||
const gasLimit = maxCallGas(currentGasLimit, runState.eei.getGasLeft(), runState) // we set TangerineWhistle or later to true here, as STATICCALL was available from Byzantium (which is after TangerineWhistle) | ||
|
||
let data = Buffer.alloc(0) | ||
|
@@ -1235,7 +1236,7 @@ export const handlers: Map<number, OpHandler> = new Map([ | |
) | ||
} | ||
|
||
accessAddressEIP2929(runState, selfdestructToAddress, 0) | ||
accessAddressEIP2929(runState, selfdestructToAddress, true, true) | ||
return runState.eei.selfDestruct(selfdestructToAddress) | ||
}, | ||
], | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a lot better than these implicit assumptions from before! 👍