Skip to content

Commit

Permalink
Merge pull request #3675 from anoma/fraccaman/test-token-funcs
Browse files Browse the repository at this point in the history
token: fix transfer to self
  • Loading branch information
mergify[bot] authored Aug 21, 2024
2 parents dbafe50 + f5268cd commit 2a3a5c8
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Make transfers with same source and destion a no-op.
([\#3675](https://github.com/anoma/namada/pull/3675))
135 changes: 133 additions & 2 deletions crates/trans_token/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,10 @@ pub fn transfer<S>(
where
S: StorageRead + StorageWrite,
{
if amount.is_zero() {
if amount.is_zero() || src == dest {
return Ok(());
}

let src_key = balance_key(token, src);
let src_balance = read_balance(storage, token, src)?;
match src_balance.checked_sub(amount) {
Expand Down Expand Up @@ -279,6 +280,7 @@ where
let mut accounts = BTreeSet::new();
accounts.extend(sources.keys().cloned());
accounts.extend(dests.keys().cloned());

let unexpected_err = || {
storage::Error::new_const(
"Computing difference between amounts should never overflow",
Expand Down Expand Up @@ -424,10 +426,139 @@ pub fn denom_to_amount(

#[cfg(test)]
mod testing {
use std::collections::BTreeMap;

use namada_core::{address, token};
use namada_storage::testing::TestStorage;

use super::{burn_tokens, credit_tokens, read_balance, read_total_supply};
use super::{
burn_tokens, credit_tokens, multi_transfer, read_balance,
read_total_supply, transfer,
};

#[test]
fn test_multi_transfer() {
let mut storage = TestStorage::default();
let native_token = address::testing::nam();

// Get one account
let addr = address::testing::gen_implicit_address();

// Credit the account some balance
let pre_balance = token::Amount::native_whole(1);
credit_tokens(&mut storage, &native_token, &addr, pre_balance).unwrap();

let pre_balance_check =
read_balance(&storage, &native_token, &addr).unwrap();

assert_eq!(pre_balance_check, pre_balance);

// sources
let sources = BTreeMap::from_iter([(
(addr.clone(), native_token.clone()),
pre_balance,
)]);

// targets
let targets = BTreeMap::from_iter([(
(addr.clone(), native_token.clone()),
pre_balance,
)]);

multi_transfer(&mut storage, &sources, &targets).unwrap();

let post_balance_check =
read_balance(&storage, &native_token, &addr).unwrap();

assert_eq!(post_balance_check, pre_balance);
}

#[test]
fn test_credit() {
let mut storage = TestStorage::default();
let native_token = address::testing::nam();

// Get one account
let addr = address::testing::gen_implicit_address();

// Credit the account some balance
let pre_balance = token::Amount::native_whole(1);
credit_tokens(&mut storage, &native_token, &addr, pre_balance).unwrap();

let total_supply_post =
read_total_supply(&storage, &native_token).unwrap();

assert_eq!(total_supply_post, pre_balance);

let post_balance =
read_balance(&storage, &native_token, &addr).unwrap();

assert_eq!(post_balance, pre_balance);
}

#[test]
fn test_transfer_to_self_is_no_op() {
let mut storage = TestStorage::default();
let native_token = address::testing::nam();

// Get one account
let addr = address::testing::gen_implicit_address();

// Credit the account some balance
let pre_balance = token::Amount::native_whole(1);
credit_tokens(&mut storage, &native_token, &addr, pre_balance).unwrap();

let total_supply_pre =
read_total_supply(&storage, &native_token).unwrap();

let transfer_result =
transfer(&mut storage, &native_token, &addr, &addr, pre_balance);
assert!(transfer_result.is_ok());

let total_supply_post =
read_total_supply(&storage, &native_token).unwrap();

assert_eq!(total_supply_post, total_supply_pre);

let post_balance =
read_balance(&storage, &native_token, &addr).unwrap();

assert_eq!(post_balance, pre_balance);
}

#[test]
fn test_transfer() {
let mut storage = TestStorage::default();
let native_token = address::testing::nam();

// Get one account
let source = address::testing::gen_implicit_address();
let target = address::testing::gen_implicit_address();

// Credit the account some balance
let pre_balance = token::Amount::native_whole(1);
credit_tokens(&mut storage, &native_token, &source, pre_balance)
.unwrap();

let total_supply_pre =
read_total_supply(&storage, &native_token).unwrap();

transfer(&mut storage, &native_token, &source, &target, pre_balance)
.unwrap();

let total_supply_post =
read_total_supply(&storage, &native_token).unwrap();

assert_eq!(total_supply_post, total_supply_pre);

let post_balance_target =
read_balance(&storage, &native_token, &target).unwrap();
let post_balance_source =
read_balance(&storage, &native_token, &source).unwrap();

assert_eq!(post_balance_target, pre_balance);
assert_eq!(post_balance_source, token::Amount::native_whole(0));
}

#[test]
fn test_burn_native_tokens() {
Expand Down

0 comments on commit 2a3a5c8

Please sign in to comment.