-
Notifications
You must be signed in to change notification settings - Fork 2
/
migrate.go
120 lines (106 loc) · 3.8 KB
/
migrate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package crossdomain
import (
"fmt"
"math/big"
"github.com/sliceledger-blockchain/slice-ledger/op-bindings/bindings"
"github.com/sliceledger-blockchain/slice-ledger/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
// 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
)
// MigrateWithdrawal will turn a LegacyWithdrawal into a bedrock
// style Withdrawal.
func MigrateWithdrawal(
withdrawal *LegacyWithdrawal,
l1CrossDomainMessenger *common.Address,
chainID *big.Int,
) (*Withdrawal, error) {
// Attempt to parse the value
value, err := withdrawal.Value()
if err != nil {
return nil, fmt.Errorf("cannot migrate withdrawal: %w", err)
}
abi, err := bindings.L1CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return nil, err
}
// Migrated withdrawals are specified as version 0. Both the
// L2ToL1MessagePasser and the CrossDomainMessenger use the same
// versioning scheme. Both should be set to version 0
versionedNonce := EncodeVersionedNonce(withdrawal.XDomainNonce, new(big.Int))
// Encode the call to `relayMessage` on the `CrossDomainMessenger`.
// The minGasLimit can safely be 0 here.
data, err := abi.Pack(
"relayMessage",
versionedNonce,
withdrawal.XDomainSender,
withdrawal.XDomainTarget,
value,
new(big.Int),
[]byte(withdrawal.XDomainData),
)
if err != nil {
return nil, fmt.Errorf("cannot abi encode relayMessage: %w", err)
}
gasLimit := MigrateWithdrawalGasLimit(data, chainID)
w := NewWithdrawal(
versionedNonce,
&predeploys.L2CrossDomainMessengerAddr,
l1CrossDomainMessenger,
value,
new(big.Int).SetUint64(gasLimit),
data,
)
return w, nil
}
// MigrateWithdrawalGasLimit computes the gas limit for the migrated withdrawal.
// The chain id is used to determine the overhead.
func MigrateWithdrawalGasLimit(data []byte, chainID *big.Int) uint64 {
// Compute the upper bound on the gas limit. This could be more
// accurate if individual 0 bytes and non zero bytes were accounted
// for.
dataCost := uint64(len(data)) * RelayPerByteDataCost
// Goerli has a lower gas limit than other chains.
var overhead uint64
if chainID.Cmp(big.NewInt(420)) == 0 {
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 minimum gas limit. This cannot be zero
gasLimit := dataCost + overhead
// Cap the gas limit to be 25 million to prevent creating withdrawals
// that go over the block gas limit.
if gasLimit > 25_000_000 {
gasLimit = 25_000_000
}
return gasLimit
}