@@ -7,7 +7,9 @@ import io.iohk.ethereum.crypto.zksnark.{BN128Fp, PairingCheck}
77import io .iohk .ethereum .crypto .zksnark .PairingCheck .G1G2Pair
88import io .iohk .ethereum .domain .Address
99import 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 }
1113import scala .util .Try
1214
1315// scalastyle:off magic.number
@@ -29,7 +31,7 @@ object PrecompiledContracts {
2931 IdAddr -> Identity
3032 )
3133
32- val byzantiumContracts = contracts ++ Map (
34+ val byzantiumAtlantisContracts = contracts ++ Map (
3335 ModExpAddr -> ModExp ,
3436 Bn128AddAddr -> Bn128Add ,
3537 Bn128MulAddr -> Bn128Mul ,
@@ -51,21 +53,25 @@ object PrecompiledContracts {
5153
5254 private def getContract (context : ProgramContext [_, _]): Option [PrecompiledContract ] = {
5355 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 ) {
5658 // byzantium and atlantis hard fork introduce the same set of precompiled contracts
57- byzantiumContracts .get(addr)
59+ byzantiumAtlantisContracts .get(addr)
5860 } else
5961 contracts.get(addr)
6062 }
6163 }
6264
6365 sealed trait PrecompiledContract {
6466 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
6668
6769 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)
6975
7076 val (result, error, gasRemaining): (ByteString , Option [ProgramError ], BigInt ) =
7177 if (g <= context.startGas)
@@ -108,8 +114,7 @@ object PrecompiledContracts {
108114
109115 }
110116
111- def gas (inputData : ByteString ): BigInt =
112- 3000
117+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = 3000
113118
114119 private def hasOnlyLastByteSet (v : ByteString ): Boolean =
115120 v.dropWhile(_ == 0 ).size == 1
@@ -119,23 +124,23 @@ object PrecompiledContracts {
119124 def exec (inputData : ByteString ): Option [ByteString ] =
120125 Some (sha256(inputData))
121126
122- def gas (inputData : ByteString ): BigInt =
127+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
123128 60 + 12 * wordsForBytes(inputData.size)
124129 }
125130
126131 object Ripemp160 extends PrecompiledContract {
127132 def exec (inputData : ByteString ): Option [ByteString ] =
128133 Some (ByteUtils .padLeft(ripemd160(inputData), 32 ))
129134
130- def gas (inputData : ByteString ): BigInt =
135+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
131136 600 + 120 * wordsForBytes(inputData.size)
132137 }
133138
134139 object Identity extends PrecompiledContract {
135140 def exec (inputData : ByteString ): Option [ByteString ] =
136141 Some (inputData)
137142
138- def gas (inputData : ByteString ): BigInt =
143+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt =
139144 15 + 3 * wordsForBytes(inputData.size)
140145 }
141146
@@ -168,7 +173,7 @@ object PrecompiledContracts {
168173 Some (ByteString (ByteUtils .bigIntegerToBytes(result.bigInteger, modLength)))
169174 }
170175
171- def gas (inputData : ByteString ): BigInt = {
176+ def gas (inputData : ByteString , etcFork : EtcFork , ethFork : EthFork ): BigInt = {
172177 val baseLength = getLength(inputData, 0 )
173178 val expLength = getLength(inputData, 1 )
174179 val modLength = getLength(inputData, 2 )
@@ -256,8 +261,11 @@ object PrecompiledContracts {
256261 }
257262
258263
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 )
261269
262270
263271 private def getCurvePointsBytes (input : ByteString ): (ByteString , ByteString , ByteString , ByteString ) = {
@@ -293,8 +301,11 @@ object PrecompiledContracts {
293301 }
294302 }
295303
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
298309
299310 private def getCurvePointsBytes (input : ByteString ): (ByteString , ByteString , ByteString ) = {
300311 (input.slice(0 , 32 ),
@@ -325,8 +336,13 @@ object PrecompiledContracts {
325336 }
326337 }
327338
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+ }
330346 }
331347
332348 // Method which stops reading another points if one of earlier ones failed (had invalid coordinates, or was not on
0 commit comments