@@ -10,47 +10,81 @@ import akka.util.ByteString.{empty => bEmpty}
10
10
import io .iohk .ethereum .crypto .kec256
11
11
import org .bouncycastle .util .encoders .Hex
12
12
13
- // EIP-1283
14
- // Spec https://eips.ethereum.org/EIPS/eip-1283
15
13
class StoreOpCodeGasPostConstantinopleSpec extends WordSpec with PropertyChecks with Matchers with TestSetup {
16
14
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
-
15
+ val defaultGaspool = 1000000
38
16
17
+ // Spec https://eips.ethereum.org/EIPS/eip-1283
39
18
" Net gas metering for SSTORE after Constantinople hard fork (EIP-1283)" in {
40
- forAll(table) {
19
+ val eip1283table = Table [String , BigInt , BigInt , BigInt ](
20
+ (" code" , " original" , " gasUsed" , " refund" ),
21
+ (" 60006000556000600055" , 0 , 412 , 0 ),
22
+ (" 60006000556001600055" , 0 , 20212 , 0 ),
23
+ (" 60016000556000600055" , 0 , 20212 , 19800 ),
24
+ (" 60016000556002600055" , 0 , 20212 , 0 ),
25
+ (" 60016000556001600055" , 0 , 20212 , 0 ),
26
+ (" 60006000556000600055" , 1 , 5212 , 15000 ),
27
+ (" 60006000556001600055" , 1 , 5212 , 4800 ),
28
+ (" 60006000556002600055" , 1 , 5212 , 0 ),
29
+ (" 60026000556000600055" , 1 , 5212 , 15000 ),
30
+ (" 60026000556003600055" , 1 , 5212 , 0 ),
31
+ (" 60026000556001600055" , 1 , 5212 , 4800 ),
32
+ (" 60026000556002600055" , 1 , 5212 , 0 ),
33
+ (" 60016000556000600055" , 1 , 5212 , 15000 ),
34
+ (" 60016000556002600055" , 1 , 5212 , 0 ),
35
+ (" 60016000556001600055" , 1 , 412 , 0 ),
36
+ (" 600160005560006000556001600055" , 0 , 40218 , 19800 ),
37
+ (" 600060005560016000556000600055" , 1 , 10218 , 19800 )
38
+ )
39
+
40
+ forAll(eip1283table) {
41
41
(code, original, gasUsed, refund) => {
42
- val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original))
42
+ val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original, defaultGaspool, EipToCheck . EIP1283 ))
43
43
44
44
result.gasUsed shouldEqual gasUsed
45
45
result.gasRefund shouldEqual refund
46
46
}
47
47
}
48
48
}
49
49
50
+ // Spec https://eips.ethereum.org/EIPS/eip-2200
51
+ " Net gas metering for SSTORE after Phoenix hard fork (EIP-2200)" in {
52
+ val eip2200table = Table [String , BigInt , BigInt , BigInt , BigInt , Option [ProgramError ]](
53
+ (" code" , " original" , " gasUsed" , " refund" , " gaspool" , " error" ),
54
+ (" 60006000556000600055" , 0 , 1612 , 0 , defaultGaspool, None ),
55
+ (" 60006000556001600055" , 0 , 20812 , 0 , defaultGaspool, None ),
56
+ (" 60016000556000600055" , 0 , 20812 , 19200 , defaultGaspool, None ),
57
+ (" 60016000556002600055" , 0 , 20812 , 0 , defaultGaspool, None ),
58
+ (" 60016000556001600055" , 0 , 20812 , 0 , defaultGaspool, None ),
59
+ (" 60006000556000600055" , 1 , 5812 , 15000 , defaultGaspool, None ),
60
+ (" 60006000556001600055" , 1 , 5812 , 4200 , defaultGaspool, None ),
61
+ (" 60006000556002600055" , 1 , 5812 , 0 , defaultGaspool, None ),
62
+ (" 60026000556000600055" , 1 , 5812 , 15000 , defaultGaspool, None ),
63
+ (" 60026000556003600055" , 1 , 5812 , 0 , defaultGaspool, None ),
64
+ (" 60026000556001600055" , 1 , 5812 , 4200 , defaultGaspool, None ),
65
+ (" 60026000556002600055" , 1 , 5812 , 0 , defaultGaspool, None ),
66
+ (" 60016000556000600055" , 1 , 5812 , 15000 , defaultGaspool, None ),
67
+ (" 60016000556002600055" , 1 , 5812 , 0 , defaultGaspool, None ),
68
+ (" 60016000556001600055" , 1 , 1612 , 0 , defaultGaspool, None ),
69
+ (" 600160005560006000556001600055" , 0 , 40818 , 19200 , defaultGaspool, None ),
70
+ (" 600060005560016000556000600055" , 1 , 10818 , 19200 , defaultGaspool, None ),
71
+ (" 6001600055" , 1 , 2306 , 0 , 2306 , Some (OutOfGas )),
72
+ (" 6001600055" , 1 , 806 , 0 , 2307 , None )
73
+ )
74
+
75
+ forAll(eip2200table) {
76
+ (code, original, gasUsed, refund, gaspool, maybeError) => {
77
+ val result = vm.exec(prepareProgramState(ByteString (Hex .decode(code)), original, gaspool, EipToCheck .EIP2200 ))
78
+
79
+ result.gasUsed shouldEqual gasUsed
80
+ result.gasRefund shouldEqual refund
81
+ result.error shouldEqual maybeError
82
+ }
83
+ }
84
+ }
50
85
}
51
86
52
87
trait TestSetup {
53
- val config = EvmConfig .ConstantinopleConfigBuilder (blockchainConfig)
54
88
val vm = new TestVM
55
89
56
90
val senderAddr = Address (0xcafebabeL)
@@ -60,7 +94,7 @@ trait TestSetup {
60
94
61
95
def defaultWorld : MockWorldState = MockWorldState ().saveAccount(senderAddr, senderAcc)
62
96
63
- val blockHeader = BlockHeader (
97
+ def prepareBlockHeader ( blockNumber : BigInt ) : BlockHeader = BlockHeader (
64
98
parentHash = bEmpty,
65
99
ommersHash = bEmpty,
66
100
beneficiary = bEmpty,
@@ -69,7 +103,7 @@ trait TestSetup {
69
103
receiptsRoot = bEmpty,
70
104
logsBloom = bEmpty,
71
105
difficulty = 1000000 ,
72
- number = blockchainConfig.constantinopleBlockNumber + 1 ,
106
+ number = blockNumber ,
73
107
gasLimit = 10000000 ,
74
108
gasUsed = 0 ,
75
109
unixTimestamp = 0 ,
@@ -78,34 +112,49 @@ trait TestSetup {
78
112
nonce = bEmpty
79
113
)
80
114
81
- def getContext (world : MockWorldState = defaultWorld, inputData : ByteString = bEmpty): PC =
115
+ def getContext (world : MockWorldState = defaultWorld, inputData : ByteString = bEmpty, eipToCheck : EipToCheck , gaspool : BigInt ): PC =
82
116
ProgramContext (
83
117
callerAddr = senderAddr,
84
118
originAddr = senderAddr,
85
119
recipientAddr = None ,
86
120
gasPrice = 1 ,
87
- startGas = 1000000 ,
121
+ startGas = gaspool ,
88
122
inputData = inputData,
89
123
value = 100 ,
90
124
endowment = 100 ,
91
125
doTransfer = true ,
92
- blockHeader = blockHeader,
126
+ blockHeader = eipToCheck. blockHeader,
93
127
callDepth = 0 ,
94
128
world = world,
95
129
initialAddressesToDelete = Set (),
96
- evmConfig = config,
130
+ evmConfig = eipToCheck. config,
97
131
originalWorld = world
98
132
)
99
133
100
- def prepareProgramState (assemblyCode : ByteString , originalValue : BigInt ): ProgramState [MockWorldState , MockStorage ] = {
134
+ def prepareProgramState (assemblyCode : ByteString , originalValue : BigInt , gaspool : BigInt , eipToCheck : EipToCheck ): ProgramState [MockWorldState , MockStorage ] = {
101
135
val newWorld = defaultWorld
102
136
.saveAccount(senderAddr, accountWithCode(assemblyCode))
103
137
.saveCode(senderAddr, assemblyCode)
104
138
.saveStorage(senderAddr, MockStorage (Map (BigInt (0 ) -> originalValue)))
105
139
106
- val context : PC = getContext(newWorld)
140
+ val context : PC = getContext(newWorld, eipToCheck = eipToCheck, gaspool = gaspool )
107
141
val env = ExecEnv (context, assemblyCode, context.originAddr)
108
142
109
143
ProgramState (vm, context, env)
110
144
}
145
+
146
+ sealed trait EipToCheck {
147
+ val blockHeader : BlockHeader
148
+ val config : EvmConfig
149
+ }
150
+ object EipToCheck {
151
+ case object EIP1283 extends EipToCheck {
152
+ override val blockHeader : BlockHeader = prepareBlockHeader(blockchainConfig.constantinopleBlockNumber + 1 )
153
+ override val config : EvmConfig = EvmConfig .ConstantinopleConfigBuilder (blockchainConfig)
154
+ }
155
+ case object EIP2200 extends EipToCheck {
156
+ override val blockHeader : BlockHeader = prepareBlockHeader(blockchainConfig.phoenixBlockNumber + 1 )
157
+ override val config : EvmConfig = EvmConfig .PhoenixConfigBuilder (blockchainConfig)
158
+ }
159
+ }
111
160
}
0 commit comments