Skip to content

Commit

Permalink
the gas price API
Browse files Browse the repository at this point in the history
Signed-off-by: Cyrill Leutwiler <[email protected]>
  • Loading branch information
xermicus committed Dec 18, 2024
1 parent 6ad7488 commit 746cfe2
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 1 deletion.
34 changes: 34 additions & 0 deletions substrate/frame/revive/fixtures/contracts/gas_price.rs
Original file line number Diff line number Diff line change
@@ -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 gas price 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::gas_price().to_le_bytes());
}
12 changes: 12 additions & 0 deletions substrate/frame/revive/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod call_builder;
mod code;
use self::{call_builder::CallSetup, code::WasmModule};
use crate::{
evm::runtime::GAS_PRICE,
exec::{Key, MomentOf},
limits,
storage::WriteOutcome,
Expand Down Expand Up @@ -798,6 +799,17 @@ mod benchmarks {
assert_eq!(U256::from_little_endian(&memory[..]), U256::from(128));
}

#[benchmark(pov_mode = Measured)]
fn seal_gas_price() {
build_runtime!(runtime, memory: []);
let result;
#[block]
{
result = runtime.bench_gas_price(memory.as_mut_slice());
}
assert_eq!(result.unwrap(), u64::from(GAS_PRICE));
}

#[benchmark(pov_mode = Measured)]
fn seal_block_number() {
build_runtime!(runtime, memory: [[0u8;32], ]);
Expand Down
21 changes: 20 additions & 1 deletion substrate/frame/revive/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
ChainExtension, Environment, Ext, RegisteredChainExtension, Result as ExtensionResult,
RetVal, ReturnFlags,
},
evm::GenericTransaction,
evm::{runtime::GAS_PRICE, GenericTransaction},
exec::Key,
limits,
primitives::CodeUploadReturnValue,
Expand Down Expand Up @@ -4363,6 +4363,25 @@ fn create1_with_value_works() {
});
}


#[test]
fn gas_price_api_works() {
let (code, _) = compile_module("gas_price").unwrap();

ExtBuilder::default().existential_deposit(100).build().execute_with(|| {
let _ = <Test as Config>::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 gas price 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()), u64::from(GAS_PRICE));
});
}

#[test]
fn call_data_size_api_works() {
let (code, _) = compile_module("call_data_size").unwrap();
Expand Down
12 changes: 12 additions & 0 deletions substrate/frame/revive/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use crate::{
address::AddressMapper,
evm::runtime::GAS_PRICE,
exec::{ExecError, ExecResult, Ext, Key},
gas::{ChargedAmount, Token},
limits,
Expand Down Expand Up @@ -322,6 +323,8 @@ pub enum RuntimeCosts {
BlockNumber,
/// Weight of calling `seal_block_hash`.
BlockHash,
/// Weight of calling `seal_gas_price`.
GasPrice,
/// Weight of calling `seal_now`.
Now,
/// Weight of calling `seal_weight_to_fee`.
Expand Down Expand Up @@ -472,6 +475,7 @@ impl<T: Config> Token<T> for RuntimeCosts {
MinimumBalance => T::WeightInfo::seal_minimum_balance(),
BlockNumber => T::WeightInfo::seal_block_number(),
BlockHash => T::WeightInfo::seal_block_hash(),
GasPrice => T::WeightInfo::seal_gas_price(),
Now => T::WeightInfo::seal_now(),
WeightToFee => T::WeightInfo::seal_weight_to_fee(),
Terminate(locked_dependencies) => T::WeightInfo::seal_terminate(locked_dependencies),
Expand Down Expand Up @@ -1559,6 +1563,14 @@ pub mod env {
)?)
}

#[stable]
/// Returns the simulated ethereum `GASPRICE` value.
/// See [`pallet_revive_uapi::HostFn::gas_price`].
fn gas_price(&mut self, memory: &mut M) -> Result<u64, TrapReason> {
self.charge_gas(RuntimeCosts::GasPrice)?;
Ok(GAS_PRICE.into())
}

/// Load the latest block timestamp into the supplied buffer
/// See [`pallet_revive_uapi::HostFn::now`].
#[stable]
Expand Down
15 changes: 15 additions & 0 deletions substrate/frame/revive/src/weights.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions substrate/frame/revive/uapi/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ pub trait HostFn: private::Sealed {
/// Returns the [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
fn chain_id(output: &mut [u8; 32]);

/// Returns the price per ref_time, akin to the EVM
/// [GASPRICE](https://www.evm.codes/?fork=cancun#3a) opcode.
fn gas_price() -> u64;

/// Stores the call data size as little endian U256 value into the supplied buffer.
///
/// # Parameters
Expand Down
5 changes: 5 additions & 0 deletions substrate/frame/revive/uapi/src/host/riscv64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ mod sys {
data_ptr: *const u8,
data_len: u32,
);
pub fn gas_price() -> u64;
pub fn call_data_size(out_ptr: *mut u8);
pub fn block_number(out_ptr: *mut u8);
pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8);
Expand Down Expand Up @@ -391,6 +392,10 @@ impl HostFn for HostFnImpl {
panic!("seal_return does not return");
}

fn gas_price() -> u64 {
unsafe { sys::gas_price() }
}

impl_wrapper_for! {
[u8; 32] => call_data_size, balance, value_transferred, now, chain_id;
[u8; 20] => address, caller, origin;
Expand Down

0 comments on commit 746cfe2

Please sign in to comment.