2. Effect of transfer on the balances of various addresses¶
What should be the effect of a transfer
of amount
between two addresses,
to
and from
?
Write a rule to capture the correct behavior. Whose balance should change by what amount?
Note that transfer
should not affect any address other than the one being transferred
to and from. Write another rule to encode the effect of transfer
on some other
address.
You can write these two properties in transfer_is_correct
and
transfer_no_effect_on_other
in
src/certora/spec.rs.
Once you have written the rule, you can run Certora Sunbeam to check it by running:
certoraRun confs/exercise2.conf
Solution
// Exercise 2
#[rule]
fn transfer_is_correct(e: Env, to: Address, from: Address, amount: i64) {
require!(
e.storage().persistent().has(&from) && e.storage().persistent().has(&to) && to != from,
"addresses exist and different"
);
let balance_from_before = Token::balance(&e, from.clone());
let balance_to_before = Token::balance(&e, to.clone());
Token::transfer(&e, from.clone(), to.clone(), amount);
let balance_from_after = Token::balance(&e, from.clone());
let balance_to_after = Token::balance(&e, to.clone());
cvt::assert!(
(balance_to_after == balance_to_before + amount)
&& (balance_from_after == balance_from_before - amount)
);
}
// Exercise 2
#[rule]
fn transfer_no_effect_on_other(e: Env, amount: i64, from: Address, to: Address, other: Address) {
require!(to != other && from != other, "addresses are all different");
let balance_other_before = Token::balance(&e, other.clone());
Token::transfer(&e, from.clone(), to.clone(), amount);
let balance_other_after = Token::balance(&e, other.clone());
cvt::assert!(balance_other_after == balance_other_before);
}