#[cfg(test)]
mod allowance_tests {
use core::ops::Add;
use odra::casper_types::U256;
use odra::host::{Deployer, HostRef, NoArgs};
use odra::prelude::*;
use crate::cep18::cep18_client_contract::Cep18ClientContract;
use crate::cep18::errors::Error::InsufficientAllowance;
use crate::cep18_token::tests::{
invert_address, setup, ALLOWANCE_AMOUNT_1, ALLOWANCE_AMOUNT_2, TRANSFER_AMOUNT_1
};
use crate::cep18_token::utils::Cep18ExampleHostRef;
fn test_approve_for(
cep18_token: &mut Cep18ExampleHostRef,
sender: Address,
owner: Address,
spender: Address
) {
let amount = TRANSFER_AMOUNT_1.into();
assert_eq!(cep18_token.allowance(&owner, &spender), 0.into());
cep18_token.env().set_caller(sender);
cep18_token.approve(&spender, &amount);
assert_eq!(cep18_token.allowance(&owner, &spender), amount);
cep18_token.approve(&spender, &(amount.add(U256::one())));
assert_eq!(
cep18_token.allowance(&owner, &spender),
amount.add(U256::one())
);
let inverted_owner = invert_address(owner);
let inverted_spender = invert_address(spender);
assert_eq!(
cep18_token.allowance(&inverted_owner, &inverted_spender),
U256::zero()
);
}
#[test]
fn should_approve_funds() {
let mut cep18_token = setup();
let owner = cep18_token.env().get_account(0);
let alice = cep18_token.env().get_account(1);
let token_address = cep18_token.address();
let client_contract = Cep18ClientContract::deploy(cep18_token.env(), NoArgs);
let another_client_contract = Cep18ClientContract::deploy(cep18_token.env(), NoArgs);
let client_contract_address = client_contract.address();
let another_client_contract_address = another_client_contract.address();
test_approve_for(&mut cep18_token, owner, owner, alice);
cep18_token.approve(&client_contract_address, &ALLOWANCE_AMOUNT_1.into());
assert_eq!(
cep18_token.allowance(&owner, &client_contract_address),
ALLOWANCE_AMOUNT_1.into()
);
client_contract.transfer_from_as_stored_contract(
token_address,
owner,
client_contract_address,
ALLOWANCE_AMOUNT_1.into()
);
assert_eq!(
cep18_token.balance_of(&client_contract_address),
ALLOWANCE_AMOUNT_1.into()
);
client_contract.approve_as_stored_contract(
token_address,
another_client_contract_address,
ALLOWANCE_AMOUNT_1.into()
);
assert_eq!(
cep18_token.allowance(&client_contract_address, &another_client_contract_address),
ALLOWANCE_AMOUNT_1.into()
);
another_client_contract.transfer_from_as_stored_contract(
token_address,
client_contract_address,
another_client_contract_address,
ALLOWANCE_AMOUNT_1.into()
);
assert_eq!(
cep18_token.balance_of(&another_client_contract_address),
ALLOWANCE_AMOUNT_1.into()
);
}
#[test]
fn should_not_transfer_from_without_enough_allowance() {
let mut cep18_token = setup();
let owner = cep18_token.env().get_account(0);
let alice = cep18_token.env().get_account(1);
cep18_token.approve(&alice, &ALLOWANCE_AMOUNT_1.into());
assert_eq!(
cep18_token.allowance(&owner, &alice),
ALLOWANCE_AMOUNT_1.into()
);
cep18_token.env().set_caller(alice);
let result =
cep18_token.try_transfer_from(&owner, &alice, &U256::from(ALLOWANCE_AMOUNT_1 + 1));
assert_eq!(result.err().unwrap(), InsufficientAllowance.into());
cep18_token.transfer_from(&owner, &alice, &U256::from(ALLOWANCE_AMOUNT_1));
}
#[test]
fn test_decrease_allowance() {
let mut cep18_token = setup();
let owner = cep18_token.env().get_account(0);
let alice = cep18_token.env().get_account(1);
cep18_token.approve(&alice, &ALLOWANCE_AMOUNT_1.into());
assert_eq!(
cep18_token.allowance(&owner, &alice),
ALLOWANCE_AMOUNT_1.into()
);
cep18_token.decrease_allowance(&alice, &ALLOWANCE_AMOUNT_2.into());
assert_eq!(
cep18_token.allowance(&owner, &alice),
(ALLOWANCE_AMOUNT_1 - ALLOWANCE_AMOUNT_2).into()
);
cep18_token.increase_allowance(&alice, &ALLOWANCE_AMOUNT_1.into());
assert_eq!(
cep18_token.allowance(&owner, &alice),
((ALLOWANCE_AMOUNT_1 * 2) - ALLOWANCE_AMOUNT_2).into()
);
}
}