diff --git a/CHANGELOG.md b/CHANGELOG.md index 56489af38e5..99b18543920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased] ### Added +- Implements the API for the `pallet-revive` host function `gas_limit` - [#2691](https://github.com/use-ink/ink/pull/2691) - Implements the API for the `pallet-revive` host function `to_account_id` - [#2578](https://github.com/use-ink/ink/pull/2578) - Add `#[ink::contract_ref]` attribute - [#2648](https://github.com/use-ink/ink/pull/2648) - Add `ink_revive_types` (and remove `pallet-revive` dependency from `ink_e2e`) - [#2657](https://github.com/use-ink/ink/pull/2657) diff --git a/crates/env/src/api.rs b/crates/env/src/api.rs index c4d1aaacec3..8490199e7dd 100644 --- a/crates/env/src/api.rs +++ b/crates/env/src/api.rs @@ -73,6 +73,13 @@ pub fn caller() -> Address { ::on_instance(TypedEnvBackend::caller) } +/// Returns the block's `ref_time` limit. +/// +/// See for more information. +pub fn gas_limit() -> u64 { + ::on_instance(TypedEnvBackend::gas_limit) +} + /// Returns the transferred value for the contract execution. /// /// # Errors diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index 71e63a9a4df..3c02d58efb2 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -228,6 +228,13 @@ pub trait TypedEnvBackend: EnvBackend { /// For more details visit: [`caller`][`crate::caller`] fn caller(&mut self) -> Address; + /// Returns the block's `ref_time` limit. + /// + /// # Note + /// + /// For more details visit: [`gas_limit`][`crate::gas_limit`] + fn gas_limit(&mut self) -> u64; + /// Returns the transferred value for the contract execution. /// /// # Note diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 930b92164a0..c7b3cfcc2ae 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -550,6 +550,10 @@ impl TypedEnvBackend for EnvInstance { .unwrap_or_else(|error| panic!("could not read `caller` property: {error:?}")) } + fn gas_limit(&mut self) -> u64 { + unimplemented!("not implemented, the off-chain environment will be removed"); + } + fn transferred_value(&mut self) -> U256 { self.get_property(Engine::value_transferred) .unwrap_or_else(|error| { diff --git a/crates/env/src/engine/on_chain/pallet_revive.rs b/crates/env/src/engine/on_chain/pallet_revive.rs index e06196b0cc5..a61d1e83879 100644 --- a/crates/env/src/engine/on_chain/pallet_revive.rs +++ b/crates/env/src/engine/on_chain/pallet_revive.rs @@ -887,6 +887,10 @@ impl TypedEnvBackend for EnvInstance { .expect("The executed contract must have a caller with a valid account id.") } + fn gas_limit(&mut self) -> u64 { + ext::gas_limit() + } + fn transferred_value(&mut self) -> U256 { let mut scope = self.scoped_buffer(); let u256: &mut [u8; 32] = scope.take(32).try_into().unwrap(); diff --git a/crates/ink/src/env_access.rs b/crates/ink/src/env_access.rs index d0544b0c539..4f990d84865 100644 --- a/crates/ink/src/env_access.rs +++ b/crates/ink/src/env_access.rs @@ -108,6 +108,37 @@ where ink_env::caller() } + /// Returns the block ref_time limit. + /// + /// # Example + /// + /// ``` + /// #[ink::contract] + /// mod my_contract { + /// #[ink(storage)] + /// pub struct MyContract; + /// + /// impl MyContract { + /// #[ink(constructor)] + /// pub fn new() -> Self { + /// Self {} + /// } + /// + /// #[ink(message)] + /// pub fn get_limit(&self) -> u64 { + /// self.env().gas_limit() + /// } + /// } + /// } + /// ``` + /// + /// # Note + /// + /// For more details visit: [`ink_env::gas_limit`] + pub fn gas_limit(self) -> u64 { + ink_env::gas_limit() + } + /// Returns the transferred value for the contract execution. /// /// # Example diff --git a/crates/ink/tests/ui/contract/pass/env-access.rs b/crates/ink/tests/ui/contract/pass/env-access.rs index ce657d817e1..e2afe0b8b40 100644 --- a/crates/ink/tests/ui/contract/pass/env-access.rs +++ b/crates/ink/tests/ui/contract/pass/env-access.rs @@ -14,6 +14,7 @@ mod contract { let _ = Self::env().block_number(); let _ = Self::env().caller(); let _ = Self::env().minimum_balance(); + let _ = Self::env().gas_limit(); let _ = Self::env().transferred_value(); let _ = Self::env().weight_to_fee(0); Self {} @@ -27,6 +28,7 @@ mod contract { let _ = self.env().block_number(); let _ = self.env().caller(); let _ = self.env().minimum_balance(); + let _ = self.env().gas_limit(); let _ = self.env().transferred_value(); let _ = self.env().weight_to_fee(0); } diff --git a/integration-tests/internal/gas-hostfns/Cargo.toml b/integration-tests/internal/gas-hostfns/Cargo.toml new file mode 100755 index 00000000000..e85364d40ba --- /dev/null +++ b/integration-tests/internal/gas-hostfns/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "gas_hostfns" +description = "E2E tests for gas related host functions" +version = "6.0.0-alpha.4" +authors = ["Use Ink "] +edition = "2021" +publish = false + +[dependencies] +ink = { path = "../../../crates/ink", default-features = false, features = ["unstable-hostfn"] } + +[dev-dependencies] +ink_e2e = { path = "../../../crates/e2e" } + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", +] +ink-as-dependency = [] +e2e-tests = [] + +[package.metadata.ink-lang] +abi = "ink" diff --git a/integration-tests/internal/gas-hostfns/lib.rs b/integration-tests/internal/gas-hostfns/lib.rs new file mode 100644 index 00000000000..8c5046541ac --- /dev/null +++ b/integration-tests/internal/gas-hostfns/lib.rs @@ -0,0 +1,55 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] +#![allow(clippy::new_without_default)] + +#[ink::contract] +mod gas_hostfns { + #[ink(storage)] + pub struct GasHostfns {} + + impl GasHostfns { + #[ink(constructor)] + pub fn new() -> Self { + Self {} + } + + /// Checks that the host function `gas_limit` works + #[ink(message)] + pub fn gas_limit(&self) -> u64 { + self.env().gas_limit() + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + use super::*; + use ink_e2e::ContractsBackend; + + type E2EResult = std::result::Result>; + + #[ink_e2e::test] + async fn e2e_gas_limit_works( + mut client: Client, + ) -> E2EResult<()> { + // given + let contract = client + .instantiate("gas_hostfns", &ink_e2e::alice(), &mut GasHostfnsRef::new()) + .submit() + .await + .expect("instantiate failed"); + let call_builder = contract.call_builder::(); + + // then + let call_res = client + .call(&ink_e2e::alice(), &call_builder.gas_limit()) + .submit() + .await + .unwrap_or_else(|err| { + panic!("call failed: {:#?}", err); + }); + + assert!(call_res.return_value() > 0); + + Ok(()) + } + } +} diff --git a/integration-tests/internal/misc-hostfns/Cargo.toml b/integration-tests/internal/misc-hostfns/Cargo.toml index 27e7b955c88..8ec9020bdc9 100755 --- a/integration-tests/internal/misc-hostfns/Cargo.toml +++ b/integration-tests/internal/misc-hostfns/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "misc_hostfns" description = "E2E tests for various host functions" -version = "6.0.0-alpha.1" +version = "6.0.0-alpha.4" authors = ["Use Ink "] edition = "2021" publish = false