@@ -24,91 +24,75 @@ import (
24
24
"github.com/XinFinOrg/XDPoSChain/params"
25
25
)
26
26
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" )
67
32
}
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 ())
70
53
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 (), common .Hash (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
80
58
}
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)
83
70
}
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
+ }
93
77
}
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
+ }
107
91
}
92
+ // EIP-2200 original clause:
93
+ //return params.SloadGasEIP2200, nil // dirty update (2.2)
94
+ return cost + params .WarmStorageReadCostEIP2929 , nil // dirty update (2.2)
108
95
}
109
- // EIP-2200 original clause:
110
- //return params.SloadGasEIP2200, nil // dirty update (2.2)
111
- return cost + WarmStorageReadCostEIP2929 , nil // dirty update (2.2)
112
96
}
113
97
114
98
// 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
124
108
// If the caller cannot afford the cost, this change will be rolled back
125
109
// If he does afford it, we can skip checking the same thing later on, during execution
126
110
evm .StateDB .AddSlotToAccessList (contract .Address (), slot )
127
- return ColdSloadCostEIP2929 , nil
111
+ return params . ColdSloadCostEIP2929 , nil
128
112
}
129
- return WarmStorageReadCostEIP2929 , nil
113
+ return params . WarmStorageReadCostEIP2929 , nil
130
114
}
131
115
132
116
// gasExtCodeCopyEIP2929 implements extcodecopy according to EIP-2929
@@ -146,7 +130,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
146
130
evm .StateDB .AddAddressToAccessList (addr )
147
131
var overflow bool
148
132
// 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 {
150
134
return 0 , ErrGasUintOverflow
151
135
}
152
136
return gas , nil
@@ -168,7 +152,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
168
152
// If the caller cannot afford the cost, this change will be rolled back
169
153
evm .StateDB .AddAddressToAccessList (addr )
170
154
// The warm storage read cost is already charged as constantGas
171
- return ColdAccountAccessCostEIP2929 - WarmStorageReadCostEIP2929 , nil
155
+ return params . ColdAccountAccessCostEIP2929 - params . WarmStorageReadCostEIP2929 , nil
172
156
}
173
157
return 0 , nil
174
158
}
@@ -180,7 +164,7 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc) gasFunc {
180
164
warmAccess := evm .StateDB .AddressInAccessList (addr )
181
165
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
182
166
// the cost to charge for cold access, if any, is Cold - Warm
183
- coldCost := ColdAccountAccessCostEIP2929 - WarmStorageReadCostEIP2929
167
+ coldCost := params . ColdAccountAccessCostEIP2929 - params . WarmStorageReadCostEIP2929
184
168
if ! warmAccess {
185
169
evm .StateDB .AddAddressToAccessList (addr )
186
170
// Charge the remaining difference here already, to correctly calculate available
@@ -212,24 +196,49 @@ var (
212
196
gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929 (gasDelegateCall )
213
197
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929 (gasStaticCall )
214
198
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929 (gasCallCode )
199
+ gasSelfdestructEIP2929 = makeSelfdestructGasFn (true )
200
+ // gasSelfdestructEIP3529 implements the changes in EIP-3529 (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
+ // gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
218
+ // Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
219
+ gasSStoreEIP3529 = makeGasSStoreFunc (params .SstoreClearsScheduleRefundEIP3529 )
215
220
)
216
221
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
233
242
}
234
- return gas , nil
243
+ return gasFunc
235
244
}
0 commit comments