From 97f73fd03dacd459b48381f4116b6ab588ecb71c Mon Sep 17 00:00:00 2001 From: jangko Date: Thu, 19 Nov 2020 13:56:22 +0700 Subject: [PATCH] implement EIP 2046 --- nimbus/constants.nim | 3 ++- nimbus/vm/interpreter/opcodes_impl.nim | 9 ++++++- nimbus/vm/interpreter/utils/utils_numeric.nim | 7 +++++ tests/all_tests.nim | 3 ++- tests/test_misc.nim | 26 +++++++++++++++++++ 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/test_misc.nim diff --git a/nimbus/constants.nim b/nimbus/constants.nim index ea730110b..129759e5c 100644 --- a/nimbus/constants.nim +++ b/nimbus/constants.nim @@ -65,4 +65,5 @@ const # and: https://github.com/ethereum/EIPs/issues/170 EIP170_CODE_SIZE_LIMIT* = 24577 - + # EIP + MaxPrecompilesAddr* = 0xFFFF diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index 68c15b382..67446d58c 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -731,7 +731,7 @@ template genCall(callName: untyped, opCode: Op): untyped = (memOutPos, memOutLen) let contractAddress = when opCode in {Call, StaticCall}: destination else: c.msg.contractAddress - let (childGasFee, childGasLimit) = c.gasCosts[opCode].c_handler( + var (childGasFee, childGasLimit) = c.gasCosts[opCode].c_handler( value, GasParams(kind: opCode, c_isNewAccount: not c.accountExists(contractAddress), @@ -742,6 +742,13 @@ template genCall(callName: untyped, opCode: Op): untyped = c_memLength: memLength )) + # EIP 2046 + # reduce gas fee for precompiles + # from 700 to 40 + when opCode == StaticCall: + if c.fork >= FkBerlin and destination.toInt <= MaxPrecompilesAddr: + childGasFee = childGasFee - 660.GasInt + if childGasFee >= 0: c.gasMeter.consumeGas(childGasFee, reason = $opCode) diff --git a/nimbus/vm/interpreter/utils/utils_numeric.nim b/nimbus/vm/interpreter/utils/utils_numeric.nim index a805d479b..1d9dad522 100644 --- a/nimbus/vm/interpreter/utils/utils_numeric.nim +++ b/nimbus/vm/interpreter/utils/utils_numeric.nim @@ -7,6 +7,7 @@ import macros, + stew/endians2, stew/ranges/ptr_arith, eth/common/eth_types, ../../../constants @@ -112,3 +113,9 @@ func safeInt*(x: Uint256): int {.inline.} = result = x.truncate(int) if x > high(int32).u256 or result < 0: result = high(int32) + +func toInt*(x: EthAddress): int = + type T = uint32 + const len = sizeof(T) + fromBytesBE(T, makeOpenArray(x[x.len-len].unsafeAddr, len)).int + \ No newline at end of file diff --git a/tests/all_tests.nim b/tests/all_tests.nim index 7c84c8c7d..ad9519dc0 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -113,4 +113,5 @@ cliBuilder: ./test_forkid, ../stateless/test_witness_keys, ../stateless/test_block_witness, - ../stateless/test_witness_json + ../stateless/test_witness_json, + ./test_misc diff --git a/tests/test_misc.nim b/tests/test_misc.nim new file mode 100644 index 000000000..7629500e4 --- /dev/null +++ b/tests/test_misc.nim @@ -0,0 +1,26 @@ +import + unittest2, stew/byteutils, + eth/common/eth_types, + ../nimbus/vm/interpreter/utils/utils_numeric + +func toAddress(n: int): EthAddress = + result[19] = n.byte + +func toAddress(a, b: int): EthAddress = + result[18] = a.byte + result[19] = b.byte + +func toAddress(a, b, c: int): EthAddress = + result[17] = a.byte + result[18] = b.byte + result[19] = c.byte + +proc miscMain*() = + suite "Misc test suite": + test "EthAddress to int": + check toAddress(0xff).toInt == 0xFF + check toAddress(0x10, 0x0).toInt == 0x1000 + check toAddress(0x10, 0x0, 0x0).toInt == 0x100000 + +when isMainModule: + miscMain()