Commit 7ee57edf authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #5648 from ethereum-optimism/clabby/migration/min-gas-fix

feat(migration): Mimic `xdm.baseGas` in `migrate.go`
parents 931e1de0 7478004b
...@@ -19,6 +19,17 @@ var ( ...@@ -19,6 +19,17 @@ var (
errLegacyStorageSlotNotFound = errors.New("cannot find storage slot") errLegacyStorageSlotNotFound = errors.New("cannot find storage slot")
) )
// Constants used by `CrossDomainMessenger.baseGas`
var (
RelayConstantOverhead uint64 = 200_000
RelayPerByteDataCost uint64 = params.TxDataNonZeroGasEIP2028
MinGasDynamicOverheadNumerator uint64 = 64
MinGasDynamicOverheadDenominator uint64 = 63
RelayCallOverhead uint64 = 40_000
RelayReservedGas uint64 = 40_000
RelayGasCheckBuffer uint64 = 5_000
)
// MigrateWithdrawals will migrate a list of pending withdrawals given a StateDB. // MigrateWithdrawals will migrate a list of pending withdrawals given a StateDB.
func MigrateWithdrawals( func MigrateWithdrawals(
withdrawals SafeFilteredWithdrawals, withdrawals SafeFilteredWithdrawals,
...@@ -112,16 +123,38 @@ func MigrateWithdrawalGasLimit(data []byte, chainID *big.Int) uint64 { ...@@ -112,16 +123,38 @@ func MigrateWithdrawalGasLimit(data []byte, chainID *big.Int) uint64 {
// Compute the upper bound on the gas limit. This could be more // Compute the upper bound on the gas limit. This could be more
// accurate if individual 0 bytes and non zero bytes were accounted // accurate if individual 0 bytes and non zero bytes were accounted
// for. // for.
dataCost := uint64(len(data)) * params.TxDataNonZeroGasEIP2028 dataCost := uint64(len(data)) * RelayPerByteDataCost
// Goerli has a lower gas limit than other chains. // Goerli has a lower gas limit than other chains.
overhead := uint64(200_000) var overhead uint64
if chainID.Cmp(big.NewInt(420)) != 0 { if chainID.Cmp(big.NewInt(420)) == 0 {
overhead = 1_000_000 overhead = uint64(200_000)
} else {
// Mimic `baseGas` from `CrossDomainMessenger.sol`
overhead = uint64(
// Constant overhead
RelayConstantOverhead +
// Dynamic overhead (EIP-150)
// We use a constant 1 million gas limit due to the overhead of simulating all migrated withdrawal
// transactions during the migration. This is a conservative estimate, and if a withdrawal
// uses more than the minimum gas limit, it will fail and need to be replayed with a higher
// gas limit.
(MinGasDynamicOverheadNumerator*1_000_000)/MinGasDynamicOverheadDenominator +
// Gas reserved for the worst-case cost of 3/5 of the `CALL` opcode's dynamic gas
// factors. (Conservative)
RelayCallOverhead +
// Relay reserved gas (to ensure execution of `relayMessage` completes after the
// subcontext finishes executing) (Conservative)
RelayReservedGas +
// Gas reserved for the execution between the `hasMinGas` check and the `CALL`
// opcode. (Conservative)
RelayGasCheckBuffer,
)
} }
// Set the outer gas limit. This cannot be zero // Set the outer minimum gas limit. This cannot be zero
gasLimit := dataCost + overhead gasLimit := dataCost + overhead
// Cap the gas limit to be 25 million to prevent creating withdrawals // Cap the gas limit to be 25 million to prevent creating withdrawals
// that go over the block gas limit. // that go over the block gas limit.
if gasLimit > 25_000_000 { if gasLimit > 25_000_000 {
......
...@@ -5,6 +5,15 @@ import { LowLevelMessage } from '../interfaces' ...@@ -5,6 +5,15 @@ import { LowLevelMessage } from '../interfaces'
const { hexDataLength } = utils const { hexDataLength } = utils
// Constants used by `CrossDomainMessenger.baseGas`
const RELAY_CONSTANT_OVERHEAD = BigNumber.from(200_000)
const RELAY_PER_BYTE_DATA_COST = BigNumber.from(16)
const MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = BigNumber.from(64)
const MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = BigNumber.from(63)
const RELAY_CALL_OVERHEAD = BigNumber.from(40_000)
const RELAY_RESERVED_GAS = BigNumber.from(40_000)
const RELAY_GAS_CHECK_BUFFER = BigNumber.from(5_000)
/** /**
* Utility for hashing a LowLevelMessage object. * Utility for hashing a LowLevelMessage object.
* *
...@@ -46,11 +55,35 @@ export const migratedWithdrawalGasLimit = ( ...@@ -46,11 +55,35 @@ export const migratedWithdrawalGasLimit = (
chainID: number chainID: number
): BigNumber => { ): BigNumber => {
// Compute the gas limit and cap at 25 million // Compute the gas limit and cap at 25 million
const dataCost = BigNumber.from(hexDataLength(data)).mul(16) const dataCost = BigNumber.from(hexDataLength(data)).mul(
let overhead = 200_000 RELAY_PER_BYTE_DATA_COST
if (chainID !== 420) { )
overhead = 1_000_000 let overhead: BigNumber
if (chainID === 420) {
overhead = BigNumber.from(200_000)
} else {
// Dynamic overhead (EIP-150)
// We use a constant 1 million gas limit due to the overhead of simulating all migrated withdrawal
// transactions during the migration. This is a conservative estimate, and if a withdrawal
// uses more than the minimum gas limit, it will fail and need to be replayed with a higher
// gas limit.
const dynamicOverhead = MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR.mul(
1_000_000
).div(MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR)
// Constant overhead
overhead = RELAY_CONSTANT_OVERHEAD.add(dynamicOverhead)
.add(RELAY_CALL_OVERHEAD)
// Gas reserved for the worst-case cost of 3/5 of the `CALL` opcode's dynamic gas
// factors. (Conservative)
// Relay reserved gas (to ensure execution of `relayMessage` completes after the
// subcontext finishes executing) (Conservative)
.add(RELAY_RESERVED_GAS)
// Gas reserved for the execution between the `hasMinGas` check and the `CALL`
// opcode. (Conservative)
.add(RELAY_GAS_CHECK_BUFFER)
} }
let minGasLimit = dataCost.add(overhead) let minGasLimit = dataCost.add(overhead)
if (minGasLimit.gt(25_000_000)) { if (minGasLimit.gt(25_000_000)) {
minGasLimit = BigNumber.from(25_000_000) minGasLimit = BigNumber.from(25_000_000)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment