diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs
index 5f8692d40..2c2e148df 100644
--- a/ethcore/evm/src/interpreter/gasometer.rs
+++ b/ethcore/evm/src/interpreter/gasometer.rs
@@ -15,7 +15,7 @@
// along with Open Ethereum. If not, see .
use std::cmp;
-use ethereum_types::{BigEndianHash, U256};
+use ethereum_types::{BigEndianHash, U256, H160, Address};
use super::u256_to_address;
use {evm, vm};
@@ -31,6 +31,8 @@ macro_rules! overflowing {
}}
}
+const PRECOMPILES_ADDRESS_LIMIT: Address = H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff]);
+
enum Request {
Gas(Cost),
GasMem(Cost, Cost),
@@ -224,7 +226,7 @@ impl Gasometer {
Request::GasMemProvide(gas, mem, Some(requested))
},
- instructions::DELEGATECALL | instructions::STATICCALL => {
+ instructions::DELEGATECALL => {
let gas = Gas::from(schedule.call_gas);
let mem = cmp::max(
mem_needed(stack.peek(4), stack.peek(5))?,
@@ -234,6 +236,23 @@ impl Gasometer {
Request::GasMemProvide(gas, mem, Some(requested))
},
+ instructions::STATICCALL => {
+ let code_address = u256_to_address(stack.peek(1));
+ let gas = if code_address <= PRECOMPILES_ADDRESS_LIMIT {
+ Gas::from(schedule.staticcall_precompile_gas)
+ } else {
+ Gas::from(schedule.call_gas)
+ };
+
+ let mem = cmp::max(
+ mem_needed(stack.peek(4), stack.peek(5))?, // out_off, out_size
+ mem_needed(stack.peek(2), stack.peek(3))? // in_off, in_size
+ );
+
+ let requested = *stack.peek(0);
+
+ Request::GasMemProvide(gas, mem, Some(requested))
+ },
instructions::CREATE => {
let start = stack.peek(1);
let len = stack.peek(2);
diff --git a/ethcore/machine/src/test_helpers.rs b/ethcore/machine/src/test_helpers.rs
index ffea1f9f9..fd8793b50 100644
--- a/ethcore/machine/src/test_helpers.rs
+++ b/ethcore/machine/src/test_helpers.rs
@@ -55,6 +55,9 @@ pub fn new_constantinople_fix_test_machine() -> Machine { load_machine(include_b
/// Create a new Foundation Istanbul era spec.
pub fn new_istanbul_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/istanbul_test.json")) }
+/// Create a new Foundation Berlin era spec.
+pub fn new_berlin_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/berlin_test.json")) }
+
/// Create a new Musicoin-MCIP3-era spec.
pub fn new_mcip3_test_machine() -> Machine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) }
diff --git a/ethcore/res/ethereum/berlin_test.json b/ethcore/res/ethereum/berlin_test.json
new file mode 100644
index 000000000..817350db0
--- /dev/null
+++ b/ethcore/res/ethereum/berlin_test.json
@@ -0,0 +1,122 @@
+{
+ "name": "Berlin (test)",
+ "engine": {
+ "Ethash": {
+ "params": {
+ "minimumDifficulty": "0x020000",
+ "difficultyBoundDivisor": "0x0800",
+ "durationLimit": "0x0d",
+ "blockReward": "0x1BC16D674EC80000",
+ "homesteadTransition": "0x0",
+ "eip100bTransition": "0x0",
+ "difficultyBombDelays": {
+ "0": 5000000
+ }
+ }
+ }
+ },
+ "params": {
+ "gasLimitBoundDivisor": "0x0400",
+ "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
+ "accountStartNonce": "0x00",
+ "maximumExtraDataSize": "0x20",
+ "minGasLimit": "0x1388",
+ "networkID" : "0x1",
+ "maxCodeSize": 24576,
+ "maxCodeSizeTransition": "0x0",
+ "eip150Transition": "0x0",
+ "eip160Transition": "0x0",
+ "eip161abcTransition": "0x0",
+ "eip161dTransition": "0x0",
+ "eip140Transition": "0x0",
+ "eip211Transition": "0x0",
+ "eip214Transition": "0x0",
+ "eip155Transition": "0x0",
+ "eip658Transition": "0x0",
+ "eip145Transition": "0x0",
+ "eip1014Transition": "0x0",
+ "eip1052Transition": "0x0",
+ "eip1283Transition": "0x0",
+ "eip1283DisableTransition": "0x0",
+ "eip1283ReenableTransition": "0x0",
+ "eip1344Transition": "0x0",
+ "eip1706Transition": "0x0",
+ "eip1884Transition": "0x0",
+ "eip2028Transition": "0x0",
+ "eip2046Transition": "0x0"
+ },
+ "genesis": {
+ "seal": {
+ "ethereum": {
+ "nonce": "0x0000000000000042",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+ },
+ "difficulty": "0x400000000",
+ "author": "0x0000000000000000000000000000000000000000",
+ "timestamp": "0x00",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
+ "gasLimit": "0x1388"
+ },
+ "accounts": {
+ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
+ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
+ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
+ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
+ "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
+ "0000000000000000000000000000000000000006": {
+ "builtin": {
+ "name": "alt_bn128_add",
+ "pricing": {
+ "0": {
+ "price": { "alt_bn128_const_operations": { "price": 500 }}
+ },
+ "0": {
+ "info": "EIP 1108 transition",
+ "price": { "alt_bn128_const_operations": { "price": 150 }}
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000007": {
+ "builtin": {
+ "name": "alt_bn128_mul",
+ "pricing": {
+ "0": {
+ "price": { "alt_bn128_const_operations": { "price": 40000 }}
+ },
+ "0": {
+ "info": "EIP 1108 transition",
+ "price": { "alt_bn128_const_operations": { "price": 6000 }}
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000008": {
+ "builtin": {
+ "name": "alt_bn128_pairing",
+ "pricing": {
+ "0": {
+ "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }}
+ },
+ "0": {
+ "info": "EIP 1108 transition",
+ "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }}
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000009": {
+ "builtin": {
+ "name": "blake2_f",
+ "activate_at": "0x00",
+ "pricing": {
+ "blake2_f": {
+ "gas_per_round": 1
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests
index d4f86ecf4..06acfb48a 160000
--- a/ethcore/res/ethereum/tests
+++ b/ethcore/res/ethereum/tests
@@ -1 +1 @@
-Subproject commit d4f86ecf4aa7c44a40bc0c972fd3e25d63ef5d92
+Subproject commit 06acfb48aee71ecb57a9ca991cf0f57b630e3469
diff --git a/ethcore/spec/src/chain.rs b/ethcore/spec/src/chain.rs
index 1a34d3911..3c53e4374 100644
--- a/ethcore/spec/src/chain.rs
+++ b/ethcore/spec/src/chain.rs
@@ -91,6 +91,7 @@ bundle_test_spec! {
"ethereum/byzantium_test" => new_byzantium_test,
"ethereum/constantinople_test" => new_constantinople_test,
"ethereum/istanbul_test" => new_istanbul_test,
+ "ethereum/berlin_test" => new_berlin_test,
"ethereum/eip150_test" => new_eip150_test,
"ethereum/eip161_test" => new_eip161_test,
"ethereum/eip210_test" => new_eip210_test,
@@ -117,6 +118,7 @@ bundle_test_machine! {
"ethereum/byzantium_test" => new_byzantium_test_machine,
"ethereum/constantinople_test" => new_constantinople_test_machine,
"ethereum/istanbul_test" => new_istanbul_test_machine,
+ "ethereum/berlin_test" => new_berlin_test_machine,
"ethereum/eip210_test" => new_eip210_test_machine,
"ethereum/frontier_test" => new_frontier_test_machine,
"ethereum/homestead_test" => new_homestead_test_machine,
diff --git a/ethcore/src/test_helpers/evm_test_client.rs b/ethcore/src/test_helpers/evm_test_client.rs
index 4985172b6..d4a252484 100644
--- a/ethcore/src/test_helpers/evm_test_client.rs
+++ b/ethcore/src/test_helpers/evm_test_client.rs
@@ -110,6 +110,7 @@ impl<'a> EvmTestClient<'a> {
ForkSpec::Constantinople => Some(spec::new_constantinople_test()),
ForkSpec::ConstantinopleFix => Some(spec::new_constantinople_fix_test()),
ForkSpec::Istanbul => Some(spec::new_istanbul_test()),
+ ForkSpec::Berlin => Some(spec::new_berlin_test()),
ForkSpec::EIP158ToByzantiumAt5 => Some(spec::new_transition_test()),
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
}
diff --git a/ethcore/types/src/engines/params.rs b/ethcore/types/src/engines/params.rs
index beb8e2113..571996d06 100644
--- a/ethcore/types/src/engines/params.rs
+++ b/ethcore/types/src/engines/params.rs
@@ -100,6 +100,8 @@ pub struct CommonParams {
pub eip1884_transition: BlockNumber,
/// Number of first block where EIP-2028 rules begin.
pub eip2028_transition: BlockNumber,
+ /// Number of first block where EIP-2046/1352 rules begin.
+ pub eip2046_transition: BlockNumber,
/// Number of first block where EIP-2200 advance transition begin.
pub eip2200_advance_transition: BlockNumber,
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
@@ -191,6 +193,9 @@ impl CommonParams {
schedule.sload_gas = 800;
schedule.sstore_dirty_gas = Some(800);
}
+ if block_number >= self.eip2046_transition {
+ schedule.staticcall_precompile_gas = 40;
+ }
if block_number >= self.eip210_transition {
schedule.blockhash_gas = 800;
}
@@ -328,6 +333,10 @@ impl From for CommonParams {
BlockNumber::max_value,
Into::into,
),
+ eip2046_transition: p.eip2046_transition.map_or_else(
+ BlockNumber::max_value,
+ Into::into,
+ ),
eip2200_advance_transition: p.eip2200_advance_transition.map_or_else(
BlockNumber::max_value,
Into::into,
diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs
index db8dacab5..8be062e57 100644
--- a/ethcore/vm/src/schedule.rs
+++ b/ethcore/vm/src/schedule.rs
@@ -71,8 +71,10 @@ pub struct Schedule {
pub log_topic_gas: usize,
/// Gas price for `CREATE` opcode
pub create_gas: usize,
- /// Gas price for `*CALL*` opcodes
+ /// Gas price for `*CALL*` opcodes, EXCEPT for staticcall to precompiles
pub call_gas: usize,
+ /// Gas price for staticcall to precompiles
+ pub staticcall_precompile_gas: usize,
/// Stipend for transfer for `CALL|CALLCODE` opcode when `value>0`
pub call_stipend: usize,
/// Additional gas required for value transfer (`CALL|CALLCODE`)
@@ -250,6 +252,7 @@ impl Schedule {
log_topic_gas: 375,
create_gas: 32000,
call_gas: 700,
+ staticcall_precompile_gas: 700,
call_stipend: 2300,
call_value_transfer_gas: 9000,
call_new_account_gas: 25000,
@@ -312,6 +315,13 @@ impl Schedule {
schedule
}
+ /// Schedule for the Berlin fork of the Ethereum main net.
+ pub fn new_berlin() -> Schedule {
+ let mut schedule = Self::new_istanbul();
+ schedule.staticcall_precompile_gas = 40; // EIPs 2046 1352
+ schedule
+ }
+
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
Schedule {
exceptional_failed_code_deposit: efcd,
@@ -341,6 +351,7 @@ impl Schedule {
log_topic_gas: 375,
create_gas: 32000,
call_gas: 40,
+ staticcall_precompile_gas: 40,
call_stipend: 2300,
call_value_transfer_gas: 9000,
call_new_account_gas: 25000,
diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs
index 575567f8d..a87b531f1 100644
--- a/ethcore/vm/src/tests.rs
+++ b/ethcore/vm/src/tests.rs
@@ -107,6 +107,13 @@ impl FakeExt {
ext
}
+ /// New fake externalities with Berlin schedule rules
+ pub fn new_berlin() -> Self {
+ let mut ext = FakeExt::default();
+ ext.schedule = Schedule::new_berlin();
+ ext
+ }
+
/// Alter fake externalities to allow wasm
pub fn with_wasm(mut self) -> Self {
self.schedule.wasm = Some(Default::default());
diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs
index a7b5f8230..df117bb1d 100644
--- a/json/src/spec/params.rs
+++ b/json/src/spec/params.rs
@@ -107,6 +107,8 @@ pub struct Params {
/// See `CommonParams` docs.
pub eip2028_transition: Option,
/// See `CommonParams` docs.
+ pub eip2046_transition: Option,
+ /// See `CommonParams` docs.
pub eip2200_advance_transition: Option,
/// See `CommonParams` docs.
pub dust_protection_transition: Option,
diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs
index 50d2c6b2e..74e224247 100644
--- a/json/src/spec/spec.rs
+++ b/json/src/spec/spec.rs
@@ -38,8 +38,10 @@ pub enum ForkSpec {
Constantinople,
/// Constantinople transition test-net
ConstantinopleFix,
- /// Istanbul (To be announced)
+ /// Istanbul (#9,069,000 2019-12-08)
Istanbul,
+ /// Berlin (To be announced)
+ Berlin,
/// Byzantium transition test-net
EIP158ToByzantiumAt5,
/// Homestead transition test-net