diff --git a/CHANGELOG.md b/CHANGELOG.md index f48ecdf137e..c85d2b0f154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Basic support for `dyn Trait` to allow cross-contract calls only with trait - [#1673](https://github.com/paritytech/ink/pull/1673) - E2E: auto detect contracts to be built - [#1691](https://github.com/paritytech/ink/pull/1691) - Add `set_code_hash` to `EnvAccess` - [#1698](https://github.com/paritytech/ink/pull/1698) +- Add `set_block_timestamp` to off-chain test api `Engine` - [#1721](https://github.com/paritytech/ink/pull/1721) ## Version 4.0.1 @@ -1931,4 +1932,4 @@ impl Contract { This is useful if the `impl` block itself does not contain any ink! constructors or messages, but you still need to access some of the "magic" provided by ink!. In the example above, you would not have -access to `emit_event` without `#[ink(impl)]`. \ No newline at end of file +access to `emit_event` without `#[ink(impl)]`. diff --git a/crates/engine/src/exec_context.rs b/crates/engine/src/exec_context.rs index 32d069e471e..57cc985dbd4 100644 --- a/crates/engine/src/exec_context.rs +++ b/crates/engine/src/exec_context.rs @@ -64,6 +64,11 @@ impl ExecContext { pub fn reset(&mut self) { *self = Default::default(); } + + /// Set the block timestamp for the execution context. + pub fn set_block_timestamp(&mut self, block_timestamp: BlockTimestamp) { + self.block_timestamp = block_timestamp + } } #[cfg(test)] diff --git a/crates/engine/src/test_api.rs b/crates/engine/src/test_api.rs index 4ee8d67745d..f99175ca935 100644 --- a/crates/engine/src/test_api.rs +++ b/crates/engine/src/test_api.rs @@ -17,6 +17,7 @@ use crate::{ types::{ AccountId, Balance, + BlockTimestamp, }, AccountError, Error, @@ -257,6 +258,11 @@ impl Engine { pub fn set_value_transferred(&mut self, value: Balance) { self.exec_context.value_transferred = value; } + + /// Set the block timestamp for the execution context. + pub fn set_block_timestamp(&mut self, new_block_timestamp: BlockTimestamp) { + self.exec_context.block_timestamp = new_block_timestamp; + } } #[cfg(test)] diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 80d0f1c8ef2..b6bc5f6601a 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -272,3 +272,21 @@ fn ecdsa_recovery_with_secp256k1_crate() { // then assert_eq!(output, pubkey.serialize()); } + +#[test] +fn setting_getting_block_timestamp() { + // given + let mut engine = Engine::new(); + let new_block_timestamp: u64 = 1000; + let output = &mut &mut get_buffer()[..]; + + // when + engine.advance_block(); + engine.set_block_timestamp(new_block_timestamp); + engine.block_timestamp(output); + + // then + let output = ::decode(&mut &output[..16]) + .expect("decoding value transferred failed"); + assert_eq!(output, new_block_timestamp); +} diff --git a/crates/env/src/engine/off_chain/test_api.rs b/crates/env/src/engine/off_chain/test_api.rs index 3e5137b9088..14b6c65fa7f 100644 --- a/crates/env/src/engine/off_chain/test_api.rs +++ b/crates/env/src/engine/off_chain/test_api.rs @@ -240,6 +240,16 @@ where }) } +/// Sets the block timestamp for the next [`advance_block`] invocation. +pub fn set_block_timestamp(value: T::Timestamp) +where + T: Environment, +{ + ::on_instance(|instance| { + instance.engine.set_block_timestamp(value); + }) +} + /// Runs the given closure test function with the default configuration /// for the off-chain environment. pub fn run_test(f: F) -> Result<()>