1
1
package io .iohk .ethereum .vm
2
2
3
+ import akka .util .ByteString
4
+ import akka .util .ByteString .{empty => bEmpty }
5
+
6
+ import org .bouncycastle .util .encoders .Hex
3
7
import org .scalacheck .Arbitrary
4
8
import org .scalacheck .Gen
5
9
import org .scalatest .funsuite .AnyFunSuite
6
10
import org .scalatest .matchers .should .Matchers
7
11
import org .scalatestplus .scalacheck .ScalaCheckPropertyChecks
8
12
13
+ import io .iohk .ethereum .Fixtures .Blocks
9
14
import io .iohk .ethereum .domain .Account
10
15
import io .iohk .ethereum .domain .Address
11
16
import io .iohk .ethereum .domain .UInt256
12
17
import io .iohk .ethereum .domain .UInt256 ._
13
18
import io .iohk .ethereum .vm .Generators ._
19
+ import io .iohk .ethereum .vm .MockWorldState .PC
20
+ import io .iohk .ethereum .vm .MockWorldState .TestVM
14
21
15
22
import Fixtures .blockchainConfig
16
23
@@ -126,7 +133,7 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
126
133
127
134
val stateOut = op.execute(stateIn)
128
135
129
- verifyGas(G_cold_account_access , stateIn, stateOut)
136
+ verifyGas(G_cold_sload , stateIn, stateOut)
130
137
assert(stateOut.accessedStorageKeys.contains((stateIn.ownAddress, offset)))
131
138
}
132
139
@@ -203,13 +210,13 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
203
210
val table = Table [UInt256 , UInt256 , Boolean , BigInt , BigInt ](
204
211
(" offset" , " value" , " alreadyAccessed" , " startGas" , " expectedGasConsumption" ),
205
212
(0 , 1 , true , G_callstipend + 1 , G_sload ),
206
- (0 , 1 , false , G_sload + G_cold_account_access , G_sload + G_cold_account_access ),
213
+ (0 , 1 , false , G_callstipend + 1 , G_sload + G_cold_sload ),
207
214
(0 , 0 , true , G_callstipend + 1 , G_sload ),
208
- (0 , 0 , false , G_sload + G_cold_account_access , G_sload + G_cold_account_access ),
215
+ (0 , 0 , false , G_callstipend + 1 , G_sload + G_cold_sload ),
209
216
(1 , 0 , true , G_callstipend + 1 , G_sload ),
210
- (1 , 0 , false , G_sload + G_cold_account_access , G_sload + G_cold_account_access ),
217
+ (1 , 0 , false , G_callstipend + 1 , G_sload + G_cold_sload ),
211
218
(1 , 1 , true , G_sset , G_sset ),
212
- (1 , 1 , false , G_sset + G_cold_account_access , G_sset + G_cold_account_access )
219
+ (1 , 1 , false , G_sset + G_cold_sload , G_sset + G_cold_sload )
213
220
)
214
221
215
222
forAll(table) { (offset, value, alreadyAccessed, startGas, expectedGasConsumption) =>
@@ -229,7 +236,7 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
229
236
forAll(Arbitrary .arbitrary[Boolean ]) { alreadyAccessed =>
230
237
val offset = 0
231
238
val value = 0
232
- val expectedGasConsumption = if (alreadyAccessed) G_sreset else G_sreset + G_cold_account_access
239
+ val expectedGasConsumption = if (alreadyAccessed) G_sreset else G_sreset + G_cold_sload
233
240
234
241
val stackIn = Stack .empty().push(value).push(offset)
235
242
val stateIn = getProgramStateGen(
@@ -244,4 +251,50 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
244
251
verifyGas(expectedGasConsumption, stateIn, stateOut, allowOOG = false )
245
252
}
246
253
}
254
+
255
+ // Testcases described in https://gist.github.com/holiman/174548cad102096858583c6fbbb0649a
256
+ test(" Gas metering after Magneto hard fork (EIP-2929)" ) {
257
+ val eip2929Table = Table [String , BigInt ](
258
+ (" code" , " gasUsed" ),
259
+ (" 60013f5060023b506003315060f13f5060f23b5060f3315060f23f5060f33b5060f1315032315030315000" , 8653 ),
260
+ (" 60006000600060ff3c60006000600060ff3c600060006000303c00" , 2835 ),
261
+ (" 60015450601160015560116002556011600255600254600154" , 44529 ),
262
+ (" 60008080808060046000f15060008080808060ff6000f15060008080808060ff6000fa50" , 2869 )
263
+ )
264
+
265
+ forAll(eip2929Table) { (code, gasUsed) =>
266
+ val defaultGaspool = 1000000
267
+ val senderAddr : Address = Address (0xcafebabeL)
268
+ val senderAcc : Account = Account (nonce = 1 , balance = 1000000 )
269
+ val defaultWorld : MockWorldState = MockWorldState ().saveAccount(senderAddr, senderAcc)
270
+
271
+ val blockHeader = Blocks .ValidBlock .header.copy(
272
+ number = Fixtures .MagnetoBlockNumber
273
+ )
274
+
275
+ val vm = new TestVM
276
+ val context : PC = ProgramContext (
277
+ callerAddr = senderAddr,
278
+ originAddr = senderAddr,
279
+ recipientAddr = None ,
280
+ gasPrice = 1 ,
281
+ startGas = defaultGaspool,
282
+ inputData = bEmpty,
283
+ value = 100 ,
284
+ endowment = 100 ,
285
+ doTransfer = true ,
286
+ blockHeader = blockHeader,
287
+ callDepth = 0 ,
288
+ world = defaultWorld,
289
+ initialAddressesToDelete = Set (),
290
+ evmConfig = config,
291
+ originalWorld = defaultWorld
292
+ )
293
+
294
+ val env = ExecEnv (context, ByteString (Hex .decode(code)), context.originAddr)
295
+ val result = vm.exec(ProgramState (vm, context, env))
296
+
297
+ result.gasUsed shouldEqual gasUsed
298
+ }
299
+ }
247
300
}
0 commit comments