@@ -7,7 +7,9 @@ import io.iohk.ethereum.crypto.zksnark.{BN128Fp, PairingCheck}
7
7
import io .iohk .ethereum .crypto .zksnark .PairingCheck .G1G2Pair
8
8
import io .iohk .ethereum .domain .Address
9
9
import io .iohk .ethereum .utils .ByteUtils
10
-
10
+ import io .iohk .ethereum .vm .BlockchainConfigForEvm .EtcForks .EtcFork
11
+ import io .iohk .ethereum .vm .BlockchainConfigForEvm .EthForks .EthFork
12
+ import io .iohk .ethereum .vm .BlockchainConfigForEvm .{EtcForks , EthForks }
11
13
import scala .util .Try
12
14
13
15
// scalastyle:off magic.number
@@ -29,7 +31,7 @@ object PrecompiledContracts {
29
31
IdAddr -> Identity
30
32
)
31
33
32
- val byzantiumContracts = contracts ++ Map (
34
+ val byzantiumAtlantisContracts = contracts ++ Map (
33
35
ModExpAddr -> ModExp ,
34
36
Bn128AddAddr -> Bn128Add ,
35
37
Bn128MulAddr -> Bn128Mul ,
@@ -51,21 +53,25 @@ object PrecompiledContracts {
51
53
52
54
private def getContract (context : ProgramContext [_, _]): Option [PrecompiledContract ] = {
53
55
context.recipientAddr.flatMap{ addr =>
54
- if (context.blockHeader.number >= context.evmConfig.blockchainConfig.byzantiumBlockNumber ||
55
- context.blockHeader.number >= context.evmConfig.blockchainConfig.atlantisBlockNumber ) {
56
+ if (context.evmConfig.blockchainConfig.ethForkForBlockNumber(context. blockHeader.number) >= EthForks . Byzantium ||
57
+ context.evmConfig.blockchainConfig.etcForkForBlockNumber(context. blockHeader.number) >= EtcForks . Atlantis ) {
56
58
// byzantium and atlantis hard fork introduce the same set of precompiled contracts
57
- byzantiumContracts .get(addr)
59
+ byzantiumAtlantisContracts .get(addr)
58
60
} else
59
61
contracts.get(addr)
60
62
}
61
63
}
62
64
63
65
sealed trait PrecompiledContract {
64
66
protected def exec (inputData : ByteString ): Option [ByteString ]
65
- protected def gas (inputData : ByteString ): BigInt
67
+ protected def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt
66
68
67
69
def run [W <: WorldStateProxy [W , S ], S <: Storage [S ]](context : ProgramContext [W , S ]): ProgramResult [W , S ] = {
68
- val g = gas(context.inputData)
70
+
71
+ val ethFork = context.evmConfig.blockchainConfig.ethForkForBlockNumber(context.blockHeader.number)
72
+ val etcFork = context.evmConfig.blockchainConfig.etcForkForBlockNumber(context.blockHeader.number)
73
+
74
+ val g = gas(context.inputData, etcFork, ethFork)
69
75
70
76
val (result, error, gasRemaining): (ByteString , Option [ProgramError ], BigInt ) =
71
77
if (g <= context.startGas)
@@ -108,8 +114,7 @@ object PrecompiledContracts {
108
114
109
115
}
110
116
111
- def gas (inputData : ByteString ): BigInt =
112
- 3000
117
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = 3000
113
118
114
119
private def hasOnlyLastByteSet (v : ByteString ): Boolean =
115
120
v.dropWhile(_ == 0 ).size == 1
@@ -119,23 +124,23 @@ object PrecompiledContracts {
119
124
def exec (inputData : ByteString ): Option [ByteString ] =
120
125
Some (sha256(inputData))
121
126
122
- def gas (inputData : ByteString ): BigInt =
127
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
123
128
60 + 12 * wordsForBytes(inputData.size)
124
129
}
125
130
126
131
object Ripemp160 extends PrecompiledContract {
127
132
def exec (inputData : ByteString ): Option [ByteString ] =
128
133
Some (ByteUtils .padLeft(ripemd160(inputData), 32 ))
129
134
130
- def gas (inputData : ByteString ): BigInt =
135
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
131
136
600 + 120 * wordsForBytes(inputData.size)
132
137
}
133
138
134
139
object Identity extends PrecompiledContract {
135
140
def exec (inputData : ByteString ): Option [ByteString ] =
136
141
Some (inputData)
137
142
138
- def gas (inputData : ByteString ): BigInt =
143
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
139
144
15 + 3 * wordsForBytes(inputData.size)
140
145
}
141
146
@@ -168,7 +173,7 @@ object PrecompiledContracts {
168
173
Some (ByteString (ByteUtils .bigIntegerToBytes(result.bigInteger, modLength)))
169
174
}
170
175
171
- def gas (inputData : ByteString ): BigInt = {
176
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = {
172
177
val baseLength = getLength(inputData, 0 )
173
178
val expLength = getLength(inputData, 1 )
174
179
val modLength = getLength(inputData, 2 )
@@ -256,8 +261,11 @@ object PrecompiledContracts {
256
261
}
257
262
258
263
259
- def gas (inputData : ByteString ): BigInt =
260
- BigInt (500 )
264
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
265
+ if (etcFork >= EtcForks .Phoenix || ethFork >= EthForks .Istanbul )
266
+ BigInt (150 ) // https://eips.ethereum.org/EIPS/eip-1108
267
+ else
268
+ BigInt (500 )
261
269
262
270
263
271
private def getCurvePointsBytes (input : ByteString ): (ByteString , ByteString , ByteString , ByteString ) = {
@@ -293,8 +301,11 @@ object PrecompiledContracts {
293
301
}
294
302
}
295
303
296
- def gas (inputData : ByteString ): BigInt =
297
- 40000
304
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
305
+ if (etcFork >= EtcForks .Phoenix || ethFork >= EthForks .Istanbul )
306
+ 6000 // https://eips.ethereum.org/EIPS/eip-1108
307
+ else
308
+ 40000
298
309
299
310
private def getCurvePointsBytes (input : ByteString ): (ByteString , ByteString , ByteString ) = {
300
311
(input.slice(0 , 32 ),
@@ -325,8 +336,13 @@ object PrecompiledContracts {
325
336
}
326
337
}
327
338
328
- def gas (inputData : ByteString ): BigInt = {
329
- 80000 * (inputData.length / inputLength) + 100000
339
+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = {
340
+ val k = inputData.length / inputLength
341
+ if (etcFork >= EtcForks .Phoenix || ethFork >= EthForks .Istanbul ){ // https://eips.ethereum.org/EIPS/eip-1108
342
+ 34000 * k + 45000
343
+ } else {
344
+ 80000 * k + 100000
345
+ }
330
346
}
331
347
332
348
// Method which stops reading another points if one of earlier ones failed (had invalid coordinates, or was not on
0 commit comments