rustnearprotocolnear

Access value of account ID after passing it as parameter to Promise::new()


The following code generates an error:

let account_id = env::signer_account_id();
let amount = 10 * 1_000_000_000_000_000_000_000_000;
Promise::new(account_id).transfer(amount);
env::log(format!("Sent {} NEAR to {}", amount, account_id).as_bytes());
    |
102 |         let account_id = env::signer_account_id();
    |             ---------- move occurs because `account_id` has type `std::string::String`, which does not implement the `Copy` trait
103 |         let amount = 10 * 1_000_000_000_000_000_000_000_000;
104 |         Promise::new(account_id).transfer(amount);
    |                      ---------- value moved here
105 |         env::log(format!("Sent {} NEAR to {}", amount, account_id).as_bytes());
    |                                                        ^^^^^^^^^^ value borrowed here after move

I am able to work around this by declaring another variable same_account_id which seems like a very bad way to get it to work.

let account_id = env::signer_account_id();
let same_account_id = env::signer_account_id();
let amount = 10 * 1_000_000_000_000_000_000_000_000;
Promise::new(account_id).transfer(amount);
env::log(format!("Sent {} NEAR to {}", amount, same_account_id).as_bytes());

What's a better/rusty way to reference account_id after it has been passed as an argument in Promise::new()?


Solution

  • String doesn't implement Copy, and Promise::new() takes its argument by value. This is why Rust says the value was moved and disallows you to use it later.

    The simplest way to fix this is to give Promise::new() an explicit copy using Clone::clone():

    Promise::new(account_id.clone()).transfer(amount);
    

    Alternatively, you could build the format string before giving account_id to the promise constructor, since the code that the format! macro emits won't take ownership of the string. This prevents a needless copy of the string.

    let msg = format!("Sent {} NEAR to {}", amount, account_id).as_bytes();
    Promise::new(account_id).transfer(amount);
    env::log(msg);