@@ -10,47 +10,76 @@ import akka.util.ByteString.{empty => bEmpty}
1010import io .iohk .ethereum .crypto .kec256
1111import org .bouncycastle .util .encoders .Hex
1212
13- // EIP-1283
14- // Spec https://eips.ethereum.org/EIPS/eip-1283
1513class StoreOpCodeGasPostConstantinopleSpec extends WordSpec with PropertyChecks with Matchers with TestSetup {
1614
17- val table = Table [String , BigInt , BigInt , BigInt ](
18- (" code" , " original" , " gasUsed" , " refund" ),
19- (" 60006000556000600055" , 0 , 412 , 0 ),
20- (" 60006000556001600055" , 0 , 20212 , 0 ),
21- (" 60016000556000600055" , 0 , 20212 , 19800 ),
22- (" 60016000556002600055" , 0 , 20212 , 0 ),
23- (" 60016000556001600055" , 0 , 20212 , 0 ),
24- (" 60006000556000600055" , 1 , 5212 , 15000 ),
25- (" 60006000556001600055" , 1 , 5212 , 4800 ),
26- (" 60006000556002600055" , 1 , 5212 , 0 ),
27- (" 60026000556000600055" , 1 , 5212 , 15000 ),
28- (" 60026000556003600055" , 1 , 5212 , 0 ),
29- (" 60026000556001600055" , 1 , 5212 , 4800 ),
30- (" 60026000556002600055" , 1 , 5212 , 0 ),
31- (" 60016000556000600055" , 1 , 5212 , 15000 ),
32- (" 60016000556002600055" , 1 , 5212 , 0 ),
33- (" 60016000556001600055" , 1 , 412 , 0 ),
34- (" 600160005560006000556001600055" , 0 , 40218 , 19800 ),
35- (" 600060005560016000556000600055" , 1 , 10218 , 19800 )
36- )
37-
38-
15+ // Spec https://eips.ethereum.org/EIPS/eip-1283
3916 " Net gas metering for SSTORE after Constantinople hard fork (EIP-1283)" in {
40- forAll(table) {
17+ val eip1283table = Table [String , BigInt , BigInt , BigInt ](
18+ (" code" , " original" , " gasUsed" , " refund" ),
19+ (" 60006000556000600055" , 0 , 412 , 0 ),
20+ (" 60006000556001600055" , 0 , 20212 , 0 ),
21+ (" 60016000556000600055" , 0 , 20212 , 19800 ),
22+ (" 60016000556002600055" , 0 , 20212 , 0 ),
23+ (" 60016000556001600055" , 0 , 20212 , 0 ),
24+ (" 60006000556000600055" , 1 , 5212 , 15000 ),
25+ (" 60006000556001600055" , 1 , 5212 , 4800 ),
26+ (" 60006000556002600055" , 1 , 5212 , 0 ),
27+ (" 60026000556000600055" , 1 , 5212 , 15000 ),
28+ (" 60026000556003600055" , 1 , 5212 , 0 ),
29+ (" 60026000556001600055" , 1 , 5212 , 4800 ),
30+ (" 60026000556002600055" , 1 , 5212 , 0 ),
31+ (" 60016000556000600055" , 1 , 5212 , 15000 ),
32+ (" 60016000556002600055" , 1 , 5212 , 0 ),
33+ (" 60016000556001600055" , 1 , 412 , 0 ),
34+ (" 600160005560006000556001600055" , 0 , 40218 , 19800 ),
35+ (" 600060005560016000556000600055" , 1 , 10218 , 19800 )
36+ )
37+
38+ forAll(eip1283table) {
4139 (code, original, gasUsed, refund) => {
42- val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original))
40+ val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original, EipToCheck . EIP1283 ))
4341
4442 result.gasUsed shouldEqual gasUsed
4543 result.gasRefund shouldEqual refund
4644 }
4745 }
4846 }
4947
48+ // Spec https://eips.ethereum.org/EIPS/eip-2200
49+ " Net gas metering for SSTORE after Phoenix hard fork (EIP-2200)" in {
50+ val eip2200table = Table [String , BigInt , BigInt , BigInt ](
51+ (" code" , " original" , " gasUsed" , " refund" ),
52+ (" 60006000556000600055" , 0 , 1612 , 0 ),
53+ (" 60006000556001600055" , 0 , 20812 , 0 ),
54+ (" 60016000556000600055" , 0 , 20812 , 19200 ),
55+ (" 60016000556002600055" , 0 , 20812 , 0 ),
56+ (" 60016000556001600055" , 0 , 20812 , 0 ),
57+ (" 60006000556000600055" , 1 , 5812 , 15000 ),
58+ (" 60006000556001600055" , 1 , 5812 , 4200 ),
59+ (" 60006000556002600055" , 1 , 5812 , 0 ),
60+ (" 60026000556000600055" , 1 , 5812 , 15000 ),
61+ (" 60026000556003600055" , 1 , 5812 , 0 ),
62+ (" 60026000556001600055" , 1 , 5812 , 4200 ),
63+ (" 60026000556002600055" , 1 , 5812 , 0 ),
64+ (" 60016000556000600055" , 1 , 5812 , 15000 ),
65+ (" 60016000556002600055" , 1 , 5812 , 0 ),
66+ (" 60016000556001600055" , 1 , 1612 , 0 ),
67+ (" 600160005560006000556001600055" , 0 , 40818 , 19200 ),
68+ (" 600060005560016000556000600055" , 1 , 10818 , 19200 )
69+ )
70+
71+ forAll(eip2200table) {
72+ (code, original, gasUsed, refund) => {
73+ val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original, EipToCheck .EIP2200 ))
74+
75+ result.gasUsed shouldEqual gasUsed
76+ result.gasRefund shouldEqual refund
77+ }
78+ }
79+ }
5080}
5181
5282trait TestSetup {
53- val config = EvmConfig .ConstantinopleConfigBuilder (blockchainConfig)
5483 val vm = new TestVM
5584
5685 val senderAddr = Address (0xcafebabeL)
@@ -60,7 +89,7 @@ trait TestSetup {
6089
6190 def defaultWorld : MockWorldState = MockWorldState ().saveAccount(senderAddr, senderAcc)
6291
63- val blockHeader = BlockHeader (
92+ def prepareBlockHeader ( blockNumber : BigInt ) : BlockHeader = BlockHeader (
6493 parentHash = bEmpty,
6594 ommersHash = bEmpty,
6695 beneficiary = bEmpty,
@@ -78,7 +107,7 @@ trait TestSetup {
78107 nonce = bEmpty
79108 )
80109
81- def getContext (world : MockWorldState = defaultWorld, inputData : ByteString = bEmpty): PC =
110+ def getContext (world : MockWorldState = defaultWorld, inputData : ByteString = bEmpty, eipToCheck : EipToCheck ): PC =
82111 ProgramContext (
83112 callerAddr = senderAddr,
84113 originAddr = senderAddr,
@@ -89,23 +118,38 @@ trait TestSetup {
89118 value = 100 ,
90119 endowment = 100 ,
91120 doTransfer = true ,
92- blockHeader = blockHeader,
121+ blockHeader = eipToCheck. blockHeader,
93122 callDepth = 0 ,
94123 world = world,
95124 initialAddressesToDelete = Set (),
96- evmConfig = config,
125+ evmConfig = eipToCheck. config,
97126 originalWorld = world
98127 )
99128
100- def prepareProgramState (assemblyCode : ByteString , originalValue : BigInt ): ProgramState [MockWorldState , MockStorage ] = {
129+ def prepareProgramState (assemblyCode : ByteString , originalValue : BigInt , eipToCheck : EipToCheck ): ProgramState [MockWorldState , MockStorage ] = {
101130 val newWorld = defaultWorld
102131 .saveAccount(senderAddr, accountWithCode(assemblyCode))
103132 .saveCode(senderAddr, assemblyCode)
104133 .saveStorage(senderAddr, MockStorage (Map (BigInt (0 ) -> originalValue)))
105134
106- val context : PC = getContext(newWorld)
135+ val context : PC = getContext(newWorld, eipToCheck = eipToCheck )
107136 val env = ExecEnv (context, assemblyCode, context.originAddr)
108137
109138 ProgramState (vm, context, env)
110139 }
140+
141+ sealed trait EipToCheck {
142+ val blockHeader : BlockHeader
143+ val config : EvmConfig
144+ }
145+ object EipToCheck {
146+ case object EIP1283 extends EipToCheck {
147+ override val blockHeader : BlockHeader = prepareBlockHeader(blockchainConfig.constantinopleBlockNumber + 1 )
148+ override val config : EvmConfig = EvmConfig .ConstantinopleConfigBuilder (blockchainConfig)
149+ }
150+ case object EIP2200 extends EipToCheck {
151+ override val blockHeader : BlockHeader = prepareBlockHeader(blockchainConfig.phoenixBlockNumber + 1 )
152+ override val config : EvmConfig = EvmConfig .PhoenixConfigBuilder (blockchainConfig)
153+ }
154+ }
111155}
0 commit comments