2

I'm playing with substrate's ink. I have written a simple smart contract which deposits funds from a user in a fixed amount.

My problem is with tests (deposit): When a user sends funds to the contract, I DO NOT see that the contract balance changes.

Can someone, please, explain or point me to the documentation why the contract's balance doesn't change?

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[ink::contract]
mod simple_deposit {

#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
    InvalidDepositSize,
}


#[ink(storage)]
pub struct SimpleDeposit {
    pub total_deposited: Balance,
    pub deposit_size: Balance,
}

impl SimpleDeposit {
    #[ink(constructor)]
    pub fn new(deposit_size: Balance) -> Self {
        Self { total_deposited: 0,
               deposit_size: deposit_size,
        }
    }

    #[ink(message)]
    pub fn balance(&self) -> Balance {
        self.total_deposited
    }

    #[ink(message, payable)]
    pub fn deposit(&mut self) -> Result<(), Error> {
        if self.env().transferred_value() != self.deposit_size {
            return Err(Error::InvalidDepositSize);
        }

        self.total_deposited += self.env().transferred_value();

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ink_lang as ink;
    use ink_lang::codegen::Env;

    use ink_env::test::set_caller as set_caller;
    use ink_env::test::set_value_transferred as set_value_transferred;

    fn bob_account() -> AccountId {
        ink_env::test::default_accounts::<ink_env::DefaultEnvironment>().bob
    }

    #[ink::test]
    fn constructor() {
        let simple_deposit = SimpleDeposit::new(15);

        assert_eq!(simple_deposit.total_deposited, 0);
        assert_eq!(simple_deposit.deposit_size, 15);
    }

    #[ink::test]
    fn deposit() {
        let mut simple_deposit = SimpleDeposit::new(15);
        let balance_before = simple_deposit.env().balance();

        set_caller::<Environment>(bob_account());
        set_value_transferred::<ink_env::DefaultEnvironment>(15);
        let res = simple_deposit.deposit();
        assert!(res.is_ok());

        let balance_after = simple_deposit.env().balance();

        assert_ne!(balance_before, balance_after);
    }
}

Sorry, I haven't searched the substrate.stackexchange yet (lack of time, maybe, will do it later).

Thanks in advance for any advices and suggestions!

here is the link to the gist on GitHub:

https://gist.github.com/vni/fb897f32244e8ff6931b286bb926a191#file-substrate-simple_deposit-ink-rs

2 Answers 2

3

Seems like set_value_transferred set the value transferred from the caller but does not update the balances

I could reproduce with this test on the contract-trasnfer example in ink repo:

#[ink::test]
fn test_transferred_value() {
    // given
    let accounts = default_accounts();
    let mut give_me = create_contract(100);

    // when
    // Push the new execution context which sets Eve as caller and
    // the `mock_transferred_value` as the value which the contract
    // will see as transferred to it.
    set_sender(accounts.eve);
    give_me.give_me(20);

    ink_env::test::set_value_transferred::<ink_env::DefaultEnvironment>(10);

    assert_eq!(get_balance(accounts.eve), 20);

    give_me.was_it_ten();

    // Panic - Should be 10
    assert_eq!(get_balance(accounts.eve), 10);
}

You can open an issue in ink! repo

1
  • Thank you very much! : ) Later will try your test, look in the sources and fire up an ink issue on GitHub. Jul 27, 2022 at 12:14
1

The off-chain engine used for contract tests did not provide means for automatically moving funds along while making contract (payable) message invocation. We have fixed that now by introducing the pay_with_call!() macro.

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.