3

I've been unit testing an ink smart contract by calling the constructor and testing various methods on the smart contract.

However, I now need to obtain the account of the contract in order to set its balance for testing purposes. How can I do this?

Lots of methods, such as getting/setting the current balance, code hash, etc, require the address of the contract.

What I've tried already:

a)

let mut contract = MyContract::default();
let code_hash = contract.env().own_code_hash(); // cannot access .env()

b)

let mut contract = MyContract::default();
let contract_addr = ink::env::account_id::<ink::env::DefaultEnvironment>(contract); // doesn't accept the contract as a parameter

c)

let mut contract = MyContract::default();
let contract_addr = ink::env::account_id::<ink::env::DefaultEnvironment>(); // using it correctly, but always returns the account [1, 1, 1, ... , 1]

let mut contract2 = MyContract::default();
let contract_addr2 = ink::env::account_id::<ink::env::DefaultEnvironment>(); // returns the account [1, 1, 1, ... , 1] again, the two contracts can't have the same address!

Essentially, I need access to the .env() in the unit tests somehow. Not sure how to do this or if this is the correct way to be doing it.

1
  • here are the function where you can set caller, calle or contract
    – Ganesh11
    May 4, 2023 at 2:18

1 Answer 1

2

Refer to the following snippet to obtain contract address:

use ink::codegen::Env;
let mut contract = MyContract::default(); // init
let address = contract.env().account_id();

You can similarly access other EnvAccess methods whose implementation is provided for off-chain environment. code_hash() & own_code_hash() is not one of them though!

Disclaimer: You need to manually set the callee before initialising a contract otherwise your contract address will be same as last set callee (which is by default [1;32]). Below is a sample implementation on how to do it.

let contract_addr: AccountId = AccountId::from([0xFF as u8; 32]);  
set_callee::<DefaultEnvironment>(contract_addr);
let mut contract = MyContract::default();

assert_eq!(contract.env().account_id(), contract_addr); // true
1
  • 1
    Thanks, the use ink::codegen::Env; was what I was missing
    – goastler
    May 4, 2023 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.