I’ve banged my head against the wall on this one.
Given the following contract function:
#[storage(read, write)]
fn distribute_funds(amount: u64) {
let total_shares = storage.total_shares.try_read().unwrap_or(1);
let mut i = 0;
// Debug: Print total shares and amount
log("Total shares: ");
log(total_shares);
log("Distributing amount: ");
log(amount);
while i < storage.shares.len() {
let (recipient, share) = storage.shares.get(i).unwrap().read();
// Debug: Print recipient and share
log("Recipient: ");
log(recipient);
log("Share: ");
log(share);
// Calculate the amount to send
let amount_to_send: u64 = ((amount * share) / total_shares);
require(amount_to_send > 0, DistributionError::CanNotSendZero);
log("Amount to send: ");
log(amount_to_send);
transfer(recipient, AssetId::base(), amount_to_send);
i += 1;
}
}
And the following test:
mod success {
use super::*;
#[tokio::test]
async fn should_distribute_funds() {
let (owner_wallet, other_wallet, another_wallet, id, instance_1, instance_2) = setup().await;
let (
owner_identity,
other_identity,
_another_identity,
) = defaults(id, owner_wallet.clone(), other_wallet.clone(), another_wallet.clone());
constructor(&instance_1, owner_identity).await;
let initial_owner_wallet_balance = owner_wallet.get_asset_balance(&AssetId::zeroed()).await.unwrap();
let initial_other_wallet_balance = other_wallet.get_asset_balance(&AssetId::zeroed()).await.unwrap();
let initial_another_wallet_balance = another_wallet.get_asset_balance(&AssetId::zeroed()).await.unwrap();
// Set shares for owner_identity and other_identity
set_shares(&instance_1, vec![owner_identity.clone(), other_identity.clone()], vec![40, 60]).await;
// Amount to be sent to the contract
let amount = 1_000;
// Call receive_funds with the specified amount
receive_funds(&instance_1, amount).await;
// Verify that the contract now has the specified amount of base_asset
let contract_balances = instance_1.get_balances().await.unwrap();
let base_asset_balance = contract_balances.get(&AssetId::zeroed()).copied().unwrap_or(0);
println!("base_asset_balance: {:?}", base_asset_balance);
assert_eq!(base_asset_balance, amount);
// Call distribute_funds with the same amount
let response = distribute_funds(&instance_1, 1_000).await;
let logs = response.decode_logs();
println!("LOGS:::");
println!("{:?}", logs);
// Verify that the correct amount of asset has been received by the wallets
let owner_balance = owner_wallet.get_asset_balance(&AssetId::zeroed()).await.unwrap();
let other_balance = other_wallet.get_asset_balance(&AssetId::zeroed()).await.unwrap();
// Calculate expected balances
let total_shares = 40 + 60;
let owner_expected_balance = initial_owner_wallet_balance + (amount * 40) / total_shares;
let other_expected_balance = initial_other_wallet_balance + (amount * 60) / total_shares;
println!("owner_balance: {:?}", owner_balance);
println!("other_balance: {:?}", other_balance);
assert_eq!(owner_balance, owner_expected_balance);
assert_eq!(other_balance, other_expected_balance);
}
}
Any idea why it would panic at the transfer? Given the test it seems that all balances on the contract and on wallets are correct, but the transfer function returns