diff --git a/substrate/frame/revive/fixtures/contracts/base_fee.rs b/substrate/frame/revive/fixtures/contracts/base_fee.rs new file mode 100644 index 000000000000..13e35a293ff4 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/base_fee.rs @@ -0,0 +1,34 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Returns the base fee back to the caller. + +#![no_std] +#![no_main] + +extern crate common; +use uapi::{HostFn, HostFnImpl as api, ReturnFlags}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + api::return_value(ReturnFlags::empty(), &api::base_fee().to_le_bytes()); +} diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index 093f7ef70674..86c1f8b7acb5 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -832,6 +832,17 @@ mod benchmarks { assert_eq!(result.unwrap(), u64::from(GAS_PRICE)); } + #[benchmark(pov_mode = Measured)] + fn seal_base_fee() { + build_runtime!(runtime, memory: []); + let result; + #[block] + { + result = runtime.bench_base_fee(memory.as_mut_slice()); + } + assert_eq!(result.unwrap(), 0); + } + #[benchmark(pov_mode = Measured)] fn seal_block_number() { build_runtime!(runtime, memory: [[0u8;32], ]); diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index a09930eaac64..8a0b1cb68c50 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -4382,6 +4382,24 @@ fn gas_price_api_works() { }); } +#[test] +fn base_fee_api_works() { + let (code, _) = compile_module("base_fee").unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 1_000_000); + + // Create fixture: Constructor does nothing + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + // Call the contract: It echoes back the value returned by the base fee API. + let received = builder::bare_call(addr).build_and_unwrap_result(); + assert_eq!(received.flags, ReturnFlags::empty()); + assert_eq!(u64::from_le_bytes(received.data[..].try_into().unwrap()), 0); + }); +} + #[test] fn call_data_size_api_works() { let (code, _) = compile_module("call_data_size").unwrap(); diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 3268e0c59c2b..3c0d3b66447e 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -327,6 +327,8 @@ pub enum RuntimeCosts { BlockHash, /// Weight of calling `seal_gas_price`. GasPrice, + /// Weight of calling `seal_base_fee`. + BaseFee, /// Weight of calling `seal_now`. Now, /// Weight of calling `seal_gas_limit`. @@ -481,6 +483,7 @@ impl Token for RuntimeCosts { BlockNumber => T::WeightInfo::seal_block_number(), BlockHash => T::WeightInfo::seal_block_hash(), GasPrice => T::WeightInfo::seal_gas_price(), + BaseFee => T::WeightInfo::seal_base_fee(), Now => T::WeightInfo::seal_now(), GasLimit => T::WeightInfo::seal_gas_limit(), WeightToFee => T::WeightInfo::seal_weight_to_fee(), @@ -1575,6 +1578,14 @@ pub mod env { Ok(GAS_PRICE.into()) } + /// Returns the simulated ethereum `BASEFEE` value. + /// See [`pallet_revive_uapi::HostFn::base_fee`]. + #[stable] + fn base_fee(&mut self, memory: &mut M) -> Result { + self.charge_gas(RuntimeCosts::BaseFee)?; + Ok(0) + } + /// Load the latest block timestamp into the supplied buffer /// See [`pallet_revive_uapi::HostFn::now`]. #[stable] diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 78eb6740c10a..d9ef3adf8987 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -85,6 +85,7 @@ pub trait WeightInfo { fn seal_call_data_size() -> Weight; fn seal_gas_limit() -> Weight; fn seal_gas_price() -> Weight; + fn seal_base_fee() -> Weight; fn seal_block_number() -> Weight; fn seal_block_hash() -> Weight; fn seal_now() -> Weight; @@ -525,6 +526,13 @@ impl WeightInfo for SubstrateWeight { // Minimum execution time: 261_000 picoseconds. Weight::from_parts(293_000, 0) } + fn seal_base_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 261_000 picoseconds. + Weight::from_parts(293_000, 0) + } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` @@ -1406,6 +1414,13 @@ impl WeightInfo for () { // Minimum execution time: 261_000 picoseconds. Weight::from_parts(293_000, 0) } + fn seal_base_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 261_000 picoseconds. + Weight::from_parts(293_000, 0) + } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index 86ccb623a1d9..037cfc083ef2 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -75,6 +75,10 @@ pub trait HostFn: private::Sealed { /// [GASPRICE](https://www.evm.codes/?fork=cancun#3a) opcode. fn gas_price() -> u64; + /// Returns the base fee, akin to the EVM + /// [BASEFEE](https://www.evm.codes/?fork=cancun#48) opcode. + fn base_fee() -> u64; + /// Returns the call data size. fn call_data_size() -> u64; diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 045ebf0fbf75..01d78da5711b 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -94,6 +94,7 @@ mod sys { data_len: u32, ); pub fn gas_price() -> u64; + pub fn base_fee() -> u64; pub fn call_data_size() -> u64; pub fn block_number(out_ptr: *mut u8); pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8); @@ -374,6 +375,10 @@ impl HostFn for HostFnImpl { unsafe { sys::gas_price() } } + fn base_fee() -> u64 { + unsafe { sys::base_fee() } + } + fn balance(output: &mut [u8; 32]) { unsafe { sys::balance(output.as_mut_ptr()) } }