Skip to content

Commit fd22cb9

Browse files
committed
core, params: implement EIP-3529
1 parent cc606be commit fd22cb9

File tree

5 files changed

+151
-114
lines changed

5 files changed

+151
-114
lines changed

core/blockchain_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3102,7 +3102,8 @@ func TestEIP2718Transition(t *testing.T) {
31023102
block := chain.GetBlockByNumber(1)
31033103

31043104
// Expected gas is intrinsic + 2 * pc + hot load + cold load, since only one load is in the access list
3105-
expected := params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas + vm.GasQuickStep*2 + vm.WarmStorageReadCostEIP2929 + vm.ColdSloadCostEIP2929
3105+
expected := params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas +
3106+
vm.GasQuickStep*2 + params.WarmStorageReadCostEIP2929 + params.ColdSloadCostEIP2929
31063107
if block.GasUsed() != expected {
31073108
t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expected, block.GasUsed())
31083109

core/state_transition.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
241241
sender := vm.AccountRef(msg.From())
242242
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
243243
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
244+
eip3529 := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
244245
contractCreation := msg.To() == nil
245246

246247
// Check clauses 4-5, subtract intrinsic gas if everything is correct
@@ -273,7 +274,13 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
273274
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
274275
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
275276
}
276-
st.refundGas()
277+
if !eip3529 {
278+
// Before EIP-3529: refunds were capped to gasUsed / 2
279+
st.refundGas(params.RefundQuotient)
280+
} else {
281+
// After EIP-3529: refunds are capped to gasUsed / 5
282+
st.refundGas(params.RefundQuotientEIP3529)
283+
}
277284
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
278285

279286
return &ExecutionResult{
@@ -283,9 +290,9 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
283290
}, nil
284291
}
285292

286-
func (st *StateTransition) refundGas() {
287-
// Apply refund counter, capped to half of the used gas.
288-
refund := st.gasUsed() / 2
293+
func (st *StateTransition) refundGas(refundQuotient uint64) {
294+
// Apply refund counter, capped to a refund quotient
295+
refund := st.gasUsed() / refundQuotient
289296
if refund > st.state.GetRefund() {
290297
refund = st.state.GetRefund()
291298
}

core/vm/eips.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
)
2626

2727
var activators = map[int]func(*JumpTable){
28+
3529: enable3529,
2829
2929: enable2929,
2930
2200: enable2200,
3031
1884: enable1884,
@@ -115,32 +116,37 @@ func enable2929(jt *JumpTable) {
115116
jt[SLOAD].constantGas = 0
116117
jt[SLOAD].dynamicGas = gasSLoadEIP2929
117118

118-
jt[EXTCODECOPY].constantGas = WarmStorageReadCostEIP2929
119+
jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929
119120
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929
120121

121-
jt[EXTCODESIZE].constantGas = WarmStorageReadCostEIP2929
122+
jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929
122123
jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck
123124

124-
jt[EXTCODEHASH].constantGas = WarmStorageReadCostEIP2929
125+
jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929
125126
jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck
126127

127-
jt[BALANCE].constantGas = WarmStorageReadCostEIP2929
128+
jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929
128129
jt[BALANCE].dynamicGas = gasEip2929AccountCheck
129130

130-
jt[CALL].constantGas = WarmStorageReadCostEIP2929
131+
jt[CALL].constantGas = params.WarmStorageReadCostEIP2929
131132
jt[CALL].dynamicGas = gasCallEIP2929
132133

133-
jt[CALLCODE].constantGas = WarmStorageReadCostEIP2929
134+
jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929
134135
jt[CALLCODE].dynamicGas = gasCallCodeEIP2929
135136

136-
jt[STATICCALL].constantGas = WarmStorageReadCostEIP2929
137+
jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929
137138
jt[STATICCALL].dynamicGas = gasStaticCallEIP2929
138139

139-
jt[DELEGATECALL].constantGas = WarmStorageReadCostEIP2929
140+
jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929
140141
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929
141142

142143
// This was previously part of the dynamic cost, but we're using it as a constantGas
143144
// factor here
144145
jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150
145146
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929
146147
}
148+
149+
func enable3529(jt *JumpTable) {
150+
jt[SSTORE].dynamicGas = gasSStoreEIP3529
151+
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP3529
152+
}

core/vm/operations_acl.go

Lines changed: 109 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -24,91 +24,75 @@ import (
2424
"github.com/ethereum/go-ethereum/params"
2525
)
2626

27-
const (
28-
ColdAccountAccessCostEIP2929 = uint64(2600) // COLD_ACCOUNT_ACCESS_COST
29-
ColdSloadCostEIP2929 = uint64(2100) // COLD_SLOAD_COST
30-
WarmStorageReadCostEIP2929 = uint64(100) // WARM_STORAGE_READ_COST
31-
)
32-
33-
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
34-
//
35-
// When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys.
36-
// If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys.
37-
// Additionally, modify the parameters defined in EIP 2200 as follows:
38-
//
39-
// Parameter Old value New value
40-
// SLOAD_GAS 800 = WARM_STORAGE_READ_COST
41-
// SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST
42-
//
43-
//The other parameters defined in EIP 2200 are unchanged.
44-
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
45-
func gasSStoreEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
46-
// If we fail the minimum gas availability invariant, fail (0)
47-
if contract.Gas <= params.SstoreSentryGasEIP2200 {
48-
return 0, errors.New("not enough gas for reentrancy sentry")
49-
}
50-
// Gas sentry honoured, do the actual gas calculation based on the stored value
51-
var (
52-
y, x = stack.Back(1), stack.peek()
53-
slot = common.Hash(x.Bytes32())
54-
current = evm.StateDB.GetState(contract.Address(), slot)
55-
cost = uint64(0)
56-
)
57-
// Check slot presence in the access list
58-
if addrPresent, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
59-
cost = ColdSloadCostEIP2929
60-
// If the caller cannot afford the cost, this change will be rolled back
61-
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
62-
if !addrPresent {
63-
// Once we're done with YOLOv2 and schedule this for mainnet, might
64-
// be good to remove this panic here, which is just really a
65-
// canary to have during testing
66-
panic("impossible case: address was not present in access list during sstore op")
27+
func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
28+
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
29+
// If we fail the minimum gas availability invariant, fail (0)
30+
if contract.Gas <= params.SstoreSentryGasEIP2200 {
31+
return 0, errors.New("not enough gas for reentrancy sentry")
6732
}
68-
}
69-
value := common.Hash(y.Bytes32())
33+
// Gas sentry honoured, do the actual gas calculation based on the stored value
34+
var (
35+
y, x = stack.Back(1), stack.peek()
36+
slot = common.Hash(x.Bytes32())
37+
current = evm.StateDB.GetState(contract.Address(), slot)
38+
cost = uint64(0)
39+
)
40+
// Check slot presence in the access list
41+
if addrPresent, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
42+
cost = params.ColdSloadCostEIP2929
43+
// If the caller cannot afford the cost, this change will be rolled back
44+
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
45+
if !addrPresent {
46+
// Once we're done with YOLOv2 and schedule this for mainnet, might
47+
// be good to remove this panic here, which is just really a
48+
// canary to have during testing
49+
panic("impossible case: address was not present in access list during sstore op")
50+
}
51+
}
52+
value := common.Hash(y.Bytes32())
7053

71-
if current == value { // noop (1)
72-
// EIP 2200 original clause:
73-
// return params.SloadGasEIP2200, nil
74-
return cost + WarmStorageReadCostEIP2929, nil // SLOAD_GAS
75-
}
76-
original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
77-
if original == current {
78-
if original == (common.Hash{}) { // create slot (2.1.1)
79-
return cost + params.SstoreSetGasEIP2200, nil
54+
if current == value { // noop (1)
55+
// EIP 2200 original clause:
56+
// return params.SloadGasEIP2200, nil
57+
return cost + params.WarmStorageReadCostEIP2929, nil // SLOAD_GAS
8058
}
81-
if value == (common.Hash{}) { // delete slot (2.1.2b)
82-
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
59+
original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
60+
if original == current {
61+
if original == (common.Hash{}) { // create slot (2.1.1)
62+
return cost + params.SstoreSetGasEIP2200, nil
63+
}
64+
if value == (common.Hash{}) { // delete slot (2.1.2b)
65+
evm.StateDB.AddRefund(clearingRefund)
66+
}
67+
// EIP-2200 original clause:
68+
// return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
69+
return cost + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929), nil // write existing slot (2.1.2)
8370
}
84-
// EIP-2200 original clause:
85-
// return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
86-
return cost + (params.SstoreResetGasEIP2200 - ColdSloadCostEIP2929), nil // write existing slot (2.1.2)
87-
}
88-
if original != (common.Hash{}) {
89-
if current == (common.Hash{}) { // recreate slot (2.2.1.1)
90-
evm.StateDB.SubRefund(params.SstoreClearsScheduleRefundEIP2200)
91-
} else if value == (common.Hash{}) { // delete slot (2.2.1.2)
92-
evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200)
71+
if original != (common.Hash{}) {
72+
if current == (common.Hash{}) { // recreate slot (2.2.1.1)
73+
evm.StateDB.SubRefund(clearingRefund)
74+
} else if value == (common.Hash{}) { // delete slot (2.2.1.2)
75+
evm.StateDB.AddRefund(clearingRefund)
76+
}
9377
}
94-
}
95-
if original == value {
96-
if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
97-
// EIP 2200 Original clause:
98-
//evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200)
99-
evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - WarmStorageReadCostEIP2929)
100-
} else { // reset to original existing slot (2.2.2.2)
101-
// EIP 2200 Original clause:
102-
// evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200)
103-
// - SSTORE_RESET_GAS redefined as (5000 - COLD_SLOAD_COST)
104-
// - SLOAD_GAS redefined as WARM_STORAGE_READ_COST
105-
// Final: (5000 - COLD_SLOAD_COST) - WARM_STORAGE_READ_COST
106-
evm.StateDB.AddRefund((params.SstoreResetGasEIP2200 - ColdSloadCostEIP2929) - WarmStorageReadCostEIP2929)
78+
if original == value {
79+
if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
80+
// EIP 2200 Original clause:
81+
//evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200)
82+
evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.WarmStorageReadCostEIP2929)
83+
} else { // reset to original existing slot (2.2.2.2)
84+
// EIP 2200 Original clause:
85+
// evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200)
86+
// - SSTORE_RESET_GAS redefined as (5000 - COLD_SLOAD_COST)
87+
// - SLOAD_GAS redefined as WARM_STORAGE_READ_COST
88+
// Final: (5000 - COLD_SLOAD_COST) - WARM_STORAGE_READ_COST
89+
evm.StateDB.AddRefund((params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - params.WarmStorageReadCostEIP2929)
90+
}
10791
}
92+
// EIP-2200 original clause:
93+
//return params.SloadGasEIP2200, nil // dirty update (2.2)
94+
return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2)
10895
}
109-
// EIP-2200 original clause:
110-
//return params.SloadGasEIP2200, nil // dirty update (2.2)
111-
return cost + WarmStorageReadCostEIP2929, nil // dirty update (2.2)
11296
}
11397

11498
// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929
@@ -124,9 +108,9 @@ func gasSLoadEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
124108
// If the caller cannot afford the cost, this change will be rolled back
125109
// If he does afford it, we can skip checking the same thing later on, during execution
126110
evm.StateDB.AddSlotToAccessList(contract.Address(), slot)
127-
return ColdSloadCostEIP2929, nil
111+
return params.ColdSloadCostEIP2929, nil
128112
}
129-
return WarmStorageReadCostEIP2929, nil
113+
return params.WarmStorageReadCostEIP2929, nil
130114
}
131115

132116
// gasExtCodeCopyEIP2929 implements extcodecopy according to EIP-2929
@@ -146,7 +130,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
146130
evm.StateDB.AddAddressToAccessList(addr)
147131
var overflow bool
148132
// We charge (cold-warm), since 'warm' is already charged as constantGas
149-
if gas, overflow = math.SafeAdd(gas, ColdAccountAccessCostEIP2929-WarmStorageReadCostEIP2929); overflow {
133+
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
150134
return 0, ErrGasUintOverflow
151135
}
152136
return gas, nil
@@ -168,7 +152,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
168152
// If the caller cannot afford the cost, this change will be rolled back
169153
evm.StateDB.AddAddressToAccessList(addr)
170154
// The warm storage read cost is already charged as constantGas
171-
return ColdAccountAccessCostEIP2929 - WarmStorageReadCostEIP2929, nil
155+
return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
172156
}
173157
return 0, nil
174158
}
@@ -180,7 +164,7 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc) gasFunc {
180164
warmAccess := evm.StateDB.AddressInAccessList(addr)
181165
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
182166
// the cost to charge for cold access, if any, is Cold - Warm
183-
coldCost := ColdAccountAccessCostEIP2929 - WarmStorageReadCostEIP2929
167+
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
184168
if !warmAccess {
185169
evm.StateDB.AddAddressToAccessList(addr)
186170
// Charge the remaining difference here already, to correctly calculate available
@@ -212,25 +196,49 @@ var (
212196
gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall)
213197
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall)
214198
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode)
199+
gasSelfdestructEIP2929 = makeSelfdestructGasFn(true)
200+
// gasSelfdestructEIP3529 implements the changes in EIP-2539 (no refunds)
201+
gasSelfdestructEIP3529 = makeSelfdestructGasFn(false)
202+
203+
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
204+
//
205+
// When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys.
206+
// If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys.
207+
// Additionally, modify the parameters defined in EIP 2200 as follows:
208+
//
209+
// Parameter Old value New value
210+
// SLOAD_GAS 800 = WARM_STORAGE_READ_COST
211+
// SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST
212+
//
213+
//The other parameters defined in EIP 2200 are unchanged.
214+
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
215+
gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200)
216+
217+
// gasSStoreEIP2539 implements gas cost for SSTORE according to EPI-2539
218+
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
219+
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
215220
)
216221

217-
func gasSelfdestructEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
218-
var (
219-
gas uint64
220-
address = common.Address(stack.peek().Bytes20())
221-
)
222-
if !evm.StateDB.AddressInAccessList(address) {
223-
// If the caller cannot afford the cost, this change will be rolled back
224-
evm.StateDB.AddAddressToAccessList(address)
225-
gas = ColdAccountAccessCostEIP2929
226-
}
227-
// if empty and transfers value
228-
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
229-
gas += params.CreateBySelfdestructGas
230-
}
231-
if !evm.StateDB.HasSuicided(contract.Address()) {
232-
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
222+
// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539
223+
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
224+
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
225+
var (
226+
gas uint64
227+
address = common.Address(stack.peek().Bytes20())
228+
)
229+
if !evm.StateDB.AddressInAccessList(address) {
230+
// If the caller cannot afford the cost, this change will be rolled back
231+
evm.StateDB.AddAddressToAccessList(address)
232+
gas = params.ColdAccountAccessCostEIP2929
233+
}
234+
// if empty and transfers value
235+
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
236+
gas += params.CreateBySelfdestructGas
237+
}
238+
if refundsEnabled && !evm.StateDB.HasSuicided(contract.Address()) {
239+
evm.StateDB.AddRefund(params.SelfdestructRefundGas)
240+
}
241+
return gas, nil
233242
}
234-
return gas, nil
235-
243+
return gasFunc
236244
}

params/protocol_params.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ const (
5757
SstoreResetGasEIP2200 uint64 = 5000 // Once per SSTORE operation from clean non-zero to something else
5858
SstoreClearsScheduleRefundEIP2200 uint64 = 15000 // Once per SSTORE operation for clearing an originally existing storage slot
5959

60+
ColdAccountAccessCostEIP2929 = uint64(2600) // COLD_ACCOUNT_ACCESS_COST
61+
ColdSloadCostEIP2929 = uint64(2100) // COLD_SLOAD_COST
62+
WarmStorageReadCostEIP2929 = uint64(100) // WARM_STORAGE_READ_COST
63+
64+
// In EIP-2200: SstoreResetGas was 5000.
65+
// In EIP-2929: SstoreResetGas was changed to '5000 - COLD_SLOAD_COST'.
66+
// In EIP-3529: SSTORE_CLEARS_SCHEDULE is defined as SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST
67+
// Which becomes: 5000 - 2100 + 1900 = 4800
68+
SstoreClearsScheduleRefundEIP3529 uint64 = SstoreResetGasEIP2200 - ColdSloadCostEIP2929 + TxAccessListStorageKeyGas
69+
6070
JumpdestGas uint64 = 1 // Once per JUMPDEST operation.
6171
EpochDuration uint64 = 30000 // Duration between proof-of-work epochs.
6272

@@ -137,6 +147,11 @@ const (
137147
Bls12381PairingPerPairGas uint64 = 23000 // Per-point pair gas price for BLS12-381 elliptic curve pairing check
138148
Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
139149
Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation
150+
151+
// The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529,
152+
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
153+
RefundQuotient uint64 = 2
154+
RefundQuotientEIP3529 uint64 = 5
140155
)
141156

142157
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations

0 commit comments

Comments
 (0)