Skip to content

Commit 9178c64

Browse files
[ETCM-1066] Add EIP-2929 VM integration tests (#1104)
1 parent 4e48c2e commit 9178c64

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

src/main/scala/io/iohk/ethereum/vm/OpCode.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ trait AddrAccessGas { self: OpCode =>
257257

258258
trait StorageAccessGas { self: OpCode =>
259259

260-
private def coldGasFn: FeeSchedule => BigInt = _.G_cold_account_access
260+
private def coldGasFn: FeeSchedule => BigInt = _.G_cold_sload
261261
private def warmGasFn: FeeSchedule => BigInt = _.G_warm_storage_read
262262

263263
override protected def baseGas[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): BigInt = {
@@ -769,7 +769,7 @@ case object SSTORE extends OpCode(0x55, 2, 0, _.G_zero) {
769769
state.config.feeSchedule.G_sreset
770770
}
771771

772-
originalCharge + OpCode.storageAccessCost(state, state.ownAddress, offset)(_ => 0, _.G_cold_account_access, _ => 0)
772+
originalCharge + OpCode.storageAccessCost(state, state.ownAddress, offset)(_ => 0, _.G_cold_sload, _ => 0)
773773
}
774774

775775
override protected def availableInContext[W <: WorldStateProxy[W, S], S <: Storage[S]]

src/test/scala/io/iohk/ethereum/vm/CallOpcodesPostEip2929Spec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class MagnetoCallOpFixture(config: EvmConfig)
2424
BlockFixtures.ValidBlock.header.copy(number = Fixtures.MagnetoBlockNumber, unixTimestamp = 0)
2525

2626
override val requiredGas: BigInt = {
27-
val storageCost = 3 * (config.feeSchedule.G_sset + config.feeSchedule.G_cold_account_access)
27+
val storageCost = 3 * (config.feeSchedule.G_sset + config.feeSchedule.G_cold_sload)
2828
val memCost = config.calcMemCost(0, 0, 32)
2929
val copyCost = config.feeSchedule.G_copy * wordsForBytes(32)
3030

src/test/scala/io/iohk/ethereum/vm/OpCodeGasSpecPostEip2929.scala

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
package io.iohk.ethereum.vm
22

3+
import akka.util.ByteString
4+
import akka.util.ByteString.{empty => bEmpty}
5+
6+
import org.bouncycastle.util.encoders.Hex
37
import org.scalacheck.Arbitrary
48
import org.scalacheck.Gen
59
import org.scalatest.funsuite.AnyFunSuite
610
import org.scalatest.matchers.should.Matchers
711
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
812

13+
import io.iohk.ethereum.Fixtures.Blocks
914
import io.iohk.ethereum.domain.Account
1015
import io.iohk.ethereum.domain.Address
1116
import io.iohk.ethereum.domain.UInt256
1217
import io.iohk.ethereum.domain.UInt256._
1318
import io.iohk.ethereum.vm.Generators._
19+
import io.iohk.ethereum.vm.MockWorldState.PC
20+
import io.iohk.ethereum.vm.MockWorldState.TestVM
1421

1522
import Fixtures.blockchainConfig
1623

@@ -126,7 +133,7 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
126133

127134
val stateOut = op.execute(stateIn)
128135

129-
verifyGas(G_cold_account_access, stateIn, stateOut)
136+
verifyGas(G_cold_sload, stateIn, stateOut)
130137
assert(stateOut.accessedStorageKeys.contains((stateIn.ownAddress, offset)))
131138
}
132139

@@ -203,13 +210,13 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
203210
val table = Table[UInt256, UInt256, Boolean, BigInt, BigInt](
204211
("offset", "value", "alreadyAccessed", "startGas", "expectedGasConsumption"),
205212
(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),
207214
(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),
209216
(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),
211218
(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)
213220
)
214221

215222
forAll(table) { (offset, value, alreadyAccessed, startGas, expectedGasConsumption) =>
@@ -229,7 +236,7 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
229236
forAll(Arbitrary.arbitrary[Boolean]) { alreadyAccessed =>
230237
val offset = 0
231238
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
233240

234241
val stackIn = Stack.empty().push(value).push(offset)
235242
val stateIn = getProgramStateGen(
@@ -244,4 +251,50 @@ class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Match
244251
verifyGas(expectedGasConsumption, stateIn, stateOut, allowOOG = false)
245252
}
246253
}
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+
}
247300
}

0 commit comments

Comments
 (0)