From 72006eccc628c6d9e2ea565211aee60d5513f8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Wed, 26 Feb 2025 21:34:25 +0200 Subject: [PATCH 1/8] resolves bullet#1 in https://github.com/near/near-sdk-rs/issues/1265#issuecomment-2634451846 --- near-sdk/src/environment/env.rs | 1 + near-sdk/src/utils/mod.rs | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/near-sdk/src/environment/env.rs b/near-sdk/src/environment/env.rs index e5e95369b..10c25feb8 100644 --- a/near-sdk/src/environment/env.rs +++ b/near-sdk/src/environment/env.rs @@ -1401,6 +1401,7 @@ pub fn promise_batch_action_delete_account( /// assert_eq!(promise_results_count(), 0); /// ``` /// More low-level info here: [`near_vm_runner::logic::VMLogic::promise_results_count`] +/// /// See example of usage [here](https://github.com/near/near-sdk-rs/blob/master/examples/cross-contract-calls/low-level/src/lib.rs) pub fn promise_results_count() -> u64 { unsafe { sys::promise_results_count() } diff --git a/near-sdk/src/utils/mod.rs b/near-sdk/src/utils/mod.rs index a1ced05cb..e58092bb1 100644 --- a/near-sdk/src/utils/mod.rs +++ b/near-sdk/src/utils/mod.rs @@ -89,18 +89,28 @@ pub fn assert_one_yocto() { } /// Returns true if promise was successful. -/// Fails if called outside a callback that received 1 promise result. -/// Uses low-level [`crate::env::promise_results_count`]. +/// +/// Calls [`crate::env::panic_str`] **host function** if called outside a callback that received precisely 1 promise result. +/// +/// Uses low-level [`crate::env::promise_results_count`] **host function**. pub fn is_promise_success() -> bool { - require!(env::promise_results_count() == 1, "Contract expected a result on the callback"); + require!( + env::promise_results_count() == 1, + "Contract expected a single result on the callback" + ); env::promise_result_internal(0).is_ok() } /// Returns the result of the promise if successful. Otherwise returns None. -/// Fails if called outside a callback that received 1 promise result. -/// Uses low-level [`crate::env::promise_results_count`] and [`crate::env::promise_result`]. +/// +/// Calls [`crate::env::panic_str`] **host function** if called outside a callback that received precisely 1 promise result. +/// +/// Uses low-level [`crate::env::promise_results_count`] and [`crate::env::promise_result`] **host functions**. pub fn promise_result_as_success() -> Option> { - require!(env::promise_results_count() == 1, "Contract expected a result on the callback"); + require!( + env::promise_results_count() == 1, + "Contract expected a single result on the callback" + ); match env::promise_result(0) { PromiseResult::Successful(result) => Some(result), _ => None, From 17deb8cb95299d7c42fb8ce417ca41325a842c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Wed, 26 Feb 2025 21:50:09 +0200 Subject: [PATCH 2/8] resolves bullet#2 in https://github.com/near/near-sdk-rs/issues/1265#issuecomment-2634451846 --- near-sdk/src/environment/env.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/near-sdk/src/environment/env.rs b/near-sdk/src/environment/env.rs index 10c25feb8..c1ed2ad43 100644 --- a/near-sdk/src/environment/env.rs +++ b/near-sdk/src/environment/env.rs @@ -1431,8 +1431,14 @@ pub fn promise_results_count() -> u64 { /// } /// }; /// ``` +/// /// More low-level info here: [`near_vm_runner::logic::VMLogic::promise_result`] -/// Example usages: [one](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/fungible_token/core_impl.rs#L178), [two](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/non_fungible_token/core/core_impl.rs#L433), [three](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/factory-contract/low-level/src/lib.rs#L61), [four](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/cross-contract-calls/low-level/src/lib.rs#L46) +/// +/// Example usages: +/// - [near-contract-standards/src/fungible_token](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/fungible_token/core_impl.rs#L178) +/// - [near-contract-standards/src/non_fungible_token](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/near-contract-standards/src/non_fungible_token/core/core_impl.rs#L433) +/// - [examples/factory-contract/low-level](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/factory-contract/low-level/src/lib.rs#L61) +/// - [examples/cross-contract-calls/low-level](https://github.com/near/near-sdk-rs/blob/189897180649bce47aefa4e5af03664ee525508d/examples/cross-contract-calls/low-level/src/lib.rs#L46) pub fn promise_result(result_idx: u64) -> PromiseResult { match promise_result_internal(result_idx) { Ok(()) => { From 4c3b6c29872ca87f18ba467a68ad3624c20c8066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Wed, 26 Feb 2025 21:58:52 +0200 Subject: [PATCH 3/8] resolves bullet#4 in https://github.com/near/near-sdk-rs/issues/1265#issuecomment-2634451846 --- near-sdk/src/environment/env.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/near-sdk/src/environment/env.rs b/near-sdk/src/environment/env.rs index c1ed2ad43..97e723830 100644 --- a/near-sdk/src/environment/env.rs +++ b/near-sdk/src/environment/env.rs @@ -1813,8 +1813,10 @@ pub fn storage_write(key: &[u8], value: &[u8]) -> bool { /// Reads the value stored under the given key. /// /// # Use cases +/// /// Storage functions are typically used to upgrade/migrate a contract state, preventing errors like `Cannot deserialize the contract state` after rolling out the breaking changes to the network. -/// For practical examples, see different implementations in [this repository](https://github.com/near-examples/update-migrate-rust). +/// +/// For practical examples, see different implementations in [`near-examples/update-migrate-rust` repo](https://github.com/near-examples/update-migrate-rust). /// /// # Examples /// ``` @@ -1824,6 +1826,9 @@ pub fn storage_write(key: &[u8], value: &[u8]) -> bool { /// storage_write(b"key", b"value"); /// assert_eq!(storage_read(b"key").unwrap(), b"value"); /// ``` +/// +/// Another example: +/// - [near-contract-standards/src/upgrade](https://github.com/near/near-sdk-rs/blob/746e4280a7e25b2036bd4e2f2c186cd76e1a7cde/near-contract-standards/src/upgrade/mod.rs?plain=1#L77) pub fn storage_read(key: &[u8]) -> Option> { match unsafe { sys::storage_read(key.len() as _, key.as_ptr() as _, ATOMIC_OP_REGISTER) } { 0 => None, From e5c11269a7223392be4f581db2d63684fd02966a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Thu, 27 Feb 2025 18:31:36 +0200 Subject: [PATCH 4/8] example: correct a wrong example, suggesting a wrong pattern of usage --- examples/adder/src/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/adder/src/lib.rs b/examples/adder/src/lib.rs index c8536a627..190d0f545 100644 --- a/examples/adder/src/lib.rs +++ b/examples/adder/src/lib.rs @@ -29,9 +29,16 @@ impl Adder { &self, #[callback_unwrap] a: DoublePair, #[callback_unwrap] b: DoublePair, - #[callback_vec] others: Vec, ) -> DoublePair { - Some(b).iter().chain(others.iter()).fold(a, |acc, el| DoublePair { + Some(b).iter().fold(a, |acc, el| DoublePair { + first: sum_pair(&acc.first, &el.first), + second: sum_pair(&acc.second, &el.second), + }) + } + + pub fn add_callback_vec(&self, #[callback_vec] elements: Vec) -> DoublePair { + let start = DoublePair { first: Pair(0, 0), second: Pair(0, 0) }; + elements.iter().fold(start, |acc, el| DoublePair { first: sum_pair(&acc.first, &el.first), second: sum_pair(&acc.second, &el.second), }) @@ -55,8 +62,7 @@ mod tests { let res = contract.view("__contract_abi").await?; - let abi_root = - serde_json::from_slice::(&zstd::decode_all(&res.result[..])?)?; + let abi_root = serde_json::from_slice::(&zstd::decode_all(&res.result[..])?)?; assert_eq!(abi_root.schema_version, "0.4.0"); assert_eq!(abi_root.metadata.name, Some("adder".to_string())); From ebc93debb7a2ea48d73d563045d6ccb21323133f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Thu, 27 Feb 2025 20:38:30 +0200 Subject: [PATCH 5/8] `#[callback_unwrap]` impl details added --- near-sdk/src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/near-sdk/src/lib.rs b/near-sdk/src/lib.rs index 25e88593d..2068c38ba 100644 --- a/near-sdk/src/lib.rs +++ b/near-sdk/src/lib.rs @@ -453,6 +453,45 @@ extern crate quickcheck; /// - [examples/adder](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/adder/src/lib.rs?plain=1#L31) /// - [examples/callback-results](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/callback-results/src/lib.rs?plain=1#L51) /// +/// ### Implementation details of `#[callback_unwrap]` macro and **host functions** calls used +/// +/// ```rust +/// # use near_sdk::near; +/// # #[near(contract_state)] +/// # pub struct Contract { /* .. */ } +/// #[near] +/// impl Contract { +/// pub fn method( +/// &mut self, +/// regular: String, +/// #[callback_unwrap] one: String, +/// #[callback_unwrap] two: String +/// ) { /* .. */ } +/// } +/// ``` +/// +/// For above `method` using the attribute on arguments, changes the body of generated function +/// +/// ```rust,no_run +/// #[no_mangle] +/// pub extern "C" fn method() { /* .. */ } +/// ``` +/// +/// in the following way: +/// +/// 1. arguments, annotated with `#[callback_unwrap]`, are no longer expected to be included into `input`, +/// deserialized in (step **3**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)). +/// 2. for each argument, annotated with `#[callback_unwrap]`: +/// 1. [`env::promise_result`] host function is called with corresponding index, starting from 0 +/// (`0u64` for argument `one`, `1u64` for argument `two` above), and saved into `promise_result` variable +/// 2. if the `promise_result` is a [`PromiseResult::Failed`] error, then [`env::panic_str`] host function is called to signal callback computation error +/// 3. otherwise, if the `promise_result` is a [`PromiseResult::Successful`], it's unwrapped and saved to a `data` variable +/// 4. `data` is deserialized similar to that as usual (step **3**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)), +/// and saved to `deserialized_n_promise` variable +/// 3. counterpart of (step **7**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)): +/// original method is called `Contract::method(&mut state, deserialized_input_success.regular, deserialized_0_promise, deserialized_1_promise)`, +/// as defined in `#[near]` annotated impl block +/// /// ## `#[near(event_json(...))]` (annotates enums) /// /// By passing `event_json` as an argument `near` will generate the relevant code to format events From b28864a08389f4a926b788422a3bc6108dafbae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Thu, 27 Feb 2025 21:41:34 +0200 Subject: [PATCH 6/8] changed referenced anchor as per changes in #1307 --- near-sdk/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/near-sdk/src/lib.rs b/near-sdk/src/lib.rs index 2068c38ba..f78d7c390 100644 --- a/near-sdk/src/lib.rs +++ b/near-sdk/src/lib.rs @@ -480,15 +480,15 @@ extern crate quickcheck; /// in the following way: /// /// 1. arguments, annotated with `#[callback_unwrap]`, are no longer expected to be included into `input`, -/// deserialized in (step **3**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)). +/// deserialized in (step **3**, [`#[near]` on mutating method](near#for-above-mutating-method-near-macro-defines-the-following-function)). /// 2. for each argument, annotated with `#[callback_unwrap]`: /// 1. [`env::promise_result`] host function is called with corresponding index, starting from 0 /// (`0u64` for argument `one`, `1u64` for argument `two` above), and saved into `promise_result` variable /// 2. if the `promise_result` is a [`PromiseResult::Failed`] error, then [`env::panic_str`] host function is called to signal callback computation error /// 3. otherwise, if the `promise_result` is a [`PromiseResult::Successful`], it's unwrapped and saved to a `data` variable -/// 4. `data` is deserialized similar to that as usual (step **3**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)), +/// 4. `data` is deserialized similar to that as usual (step **3**, [`#[near]` on mutating method](near#for-above-mutating-method-near-macro-defines-the-following-function)), /// and saved to `deserialized_n_promise` variable -/// 3. counterpart of (step **7**, [`#[near]`](near#for-above-mutating-method-macro-defines-the-following-function)): +/// 3. counterpart of (step **7**, [`#[near]` on mutating method](near#for-above-mutating-method-near-macro-defines-the-following-function)): /// original method is called `Contract::method(&mut state, deserialized_input_success.regular, deserialized_0_promise, deserialized_1_promise)`, /// as defined in `#[near]` annotated impl block /// From 40196cb760b006e8863720cb6b4880910b3177be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Thu, 27 Feb 2025 22:26:16 +0200 Subject: [PATCH 7/8] small amendments --- near-sdk/src/lib.rs | 2 +- near-sdk/src/utils/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/near-sdk/src/lib.rs b/near-sdk/src/lib.rs index f78d7c390..6ed5c722d 100644 --- a/near-sdk/src/lib.rs +++ b/near-sdk/src/lib.rs @@ -470,7 +470,7 @@ extern crate quickcheck; /// } /// ``` /// -/// For above `method` using the attribute on arguments, changes the body of generated function +/// For above `method` using the attribute on arguments, changes the body of function generated in [`#[near]` on mutating method](near#for-above-mutating-method-near-macro-defines-the-following-function) /// /// ```rust,no_run /// #[no_mangle] diff --git a/near-sdk/src/utils/mod.rs b/near-sdk/src/utils/mod.rs index e58092bb1..dc6ce8c44 100644 --- a/near-sdk/src/utils/mod.rs +++ b/near-sdk/src/utils/mod.rs @@ -92,7 +92,7 @@ pub fn assert_one_yocto() { /// /// Calls [`crate::env::panic_str`] **host function** if called outside a callback that received precisely 1 promise result. /// -/// Uses low-level [`crate::env::promise_results_count`] **host function**. +/// Uses low-level [`crate::env::promise_results_count`] and [`crate::env::promise_result`] **host functions**. pub fn is_promise_success() -> bool { require!( env::promise_results_count() == 1, From 022c9afd0e52a15e5a9731ef2290c9a68aff452b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= Date: Fri, 28 Feb 2025 18:01:25 +0200 Subject: [PATCH 8/8] resolves https://github.com/near/near-sdk-rs/pull/1319#discussion_r1975334380 --- near-sdk/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/near-sdk/src/lib.rs b/near-sdk/src/lib.rs index 6ed5c722d..4a45c5853 100644 --- a/near-sdk/src/lib.rs +++ b/near-sdk/src/lib.rs @@ -447,11 +447,11 @@ extern crate quickcheck; /// /// ### Other examples within repo: /// -/// - `Cross-Contract Factorial` again [examples/cross-contract-calls](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/cross-contract-calls/high-level/src/lib.rs?plain=1#L26) +/// - `Cross-Contract Factorial` again [examples/cross-contract-calls](https://github.com/near/near-sdk-rs/tree/master/examples/cross-contract-calls/high-level/src/lib.rs?plain=1#L26) /// - same example as [above](near#example-with-cross-contract-factorial), but uses [`Promise::then`] instead of [`env`](mod@env) host functions calls to set up a callback of `factorial_mult` -/// - [examples/adder](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/adder/src/lib.rs?plain=1#L30) -/// - [examples/adder](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/adder/src/lib.rs?plain=1#L31) -/// - [examples/callback-results](https://github.com/near/near-sdk-rs/blob/9596835369467cac6198e8de9a4b72a38deee4a5/examples/callback-results/src/lib.rs?plain=1#L51) +/// - [examples/adder](https://github.com/near/near-sdk-rs/tree/master/examples/adder/src/lib.rs?plain=1#L30) +/// - [examples/adder](https://github.com/near/near-sdk-rs/tree/master/examples/adder/src/lib.rs?plain=1#L31) +/// - [examples/callback-results](https://github.com/near/near-sdk-rs/tree/master/examples/callback-results/src/lib.rs?plain=1#L51) /// /// ### Implementation details of `#[callback_unwrap]` macro and **host functions** calls used ///