Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7a7ff8e
test: completed test coverage task
clintjeff2 Feb 25, 2026
9d26e92
final fix
clintjeff2 Feb 25, 2026
c8e631d
Merge branch 'main' into test-coverage
clintjeff2 Feb 25, 2026
784853a
final fix
clintjeff2 Feb 25, 2026
4e14d7d
final
clintjeff2 Feb 25, 2026
ab37400
fixed clippy
clintjeff2 Feb 25, 2026
dbf067f
coverage achieved
clintjeff2 Feb 25, 2026
25b0862
Merge branch 'test-coverage' of https://github.com/clintjeff2/Callora…
clintjeff2 Feb 25, 2026
8a6c452
passed coverage test
clintjeff2 Feb 25, 2026
1ac5736
fixed failing formating
clintjeff2 Feb 25, 2026
ef3e137
Merge branch 'main' into test-coverage
clintjeff2 Feb 25, 2026
eeb64f8
final
clintjeff2 Feb 25, 2026
94e4ebe
final
clintjeff2 Feb 25, 2026
0194071
Merge branch 'main' into unit-indempotency
clintjeff2 Feb 25, 2026
ea1bdc6
final
clintjeff2 Feb 25, 2026
b6d2bfe
Merge branch 'main' into test-coverage
clintjeff2 Feb 25, 2026
24fa055
Merge branch 'main' into unit-indempotency
clintjeff2 Feb 25, 2026
d04a498
ignore
clintjeff2 Feb 25, 2026
336b7a7
Merge branch 'test-coverage' of https://github.com/clintjeff2/Callora…
clintjeff2 Feb 25, 2026
bc0a3cf
final
clintjeff2 Feb 25, 2026
3e23eab
final
clintjeff2 Feb 25, 2026
ce93439
final
clintjeff2 Feb 25, 2026
9db92bb
final
clintjeff2 Feb 25, 2026
e87aaa0
no more fixes
clintjeff2 Feb 25, 2026
4100db8
Merge branch 'main' into test-coverage
clintjeff2 Feb 25, 2026
bb76929
Merge branch 'test-coverage' of https://github.com/clintjeff2/Callora…
clintjeff2 Feb 25, 2026
dd34971
fix tests
clintjeff2 Feb 25, 2026
f15b1f6
test: ensured test went up to 100% coverage
clintjeff2 Feb 26, 2026
905e4be
format fix
clintjeff2 Feb 26, 2026
920254c
updated
clintjeff2 Feb 26, 2026
962af16
coverage good
clintjeff2 Feb 26, 2026
9902df7
first fix
clintjeff2 Feb 26, 2026
58e75dc
fixed all conflicts
clintjeff2 Feb 26, 2026
9bfdc1c
Merge branch 'main' into test-coverage
greatest0fallt1me Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions contracts/revenue_pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@ impl RevenuePool {
if env.storage().instance().has(&Symbol::new(&env, ADMIN_KEY)) {
panic!("revenue pool already initialized");
}
env.storage()
.instance()
.set(&Symbol::new(&env, ADMIN_KEY), &admin);
env.storage()
.instance()
.set(&Symbol::new(&env, USDC_KEY), &usdc_token);
let inst = env.storage().instance();
inst.set(&Symbol::new(&env, ADMIN_KEY), &admin);
inst.set(&Symbol::new(&env, USDC_KEY), &usdc_token);

env.events()
.publish((Symbol::new(&env, "init"), admin), usdc_token);
Expand All @@ -49,9 +46,8 @@ impl RevenuePool {
if caller != current {
panic!("unauthorized: caller is not admin");
}
env.storage()
.instance()
.set(&Symbol::new(&env, ADMIN_KEY), &new_admin);
let inst = env.storage().instance();
inst.set(&Symbol::new(&env, ADMIN_KEY), &new_admin);
}

/// Placeholder: record that payment was received (e.g. from vault).
Expand Down Expand Up @@ -96,7 +92,7 @@ impl RevenuePool {
.storage()
.instance()
.get(&Symbol::new(&env, USDC_KEY))
.unwrap_or_else(|| panic!("revenue pool not initialized"));
.expect("revenue pool not initialized");
let usdc = token::Client::new(&env, &usdc_address);

let contract_address = env.current_contract_address();
Expand Down Expand Up @@ -138,7 +134,7 @@ impl RevenuePool {
.storage()
.instance()
.get(&Symbol::new(&env, USDC_KEY))
.unwrap_or_else(|| panic!("revenue pool not initialized"));
.expect("revenue pool not initialized");
let usdc = token::Client::new(&env, &usdc_address);

let contract_address = env.current_contract_address();
Expand Down
158 changes: 111 additions & 47 deletions contracts/revenue_pool/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate std;

use super::*;
use soroban_sdk::testutils::{Address as _, Events as _};
use soroban_sdk::{token, vec};
use soroban_sdk::token;

fn create_usdc<'a>(
env: &'a Env,
Expand Down Expand Up @@ -147,59 +147,117 @@ fn receive_payment_emits_event() {
}

#[test]
fn batch_distribute_success() {
#[should_panic(expected = "unauthorized: caller is not admin")]
fn set_admin_unauthorized_panics() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let dev1 = Address::generate(&env);
let dev2 = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, usdc_client, usdc_admin) = create_usdc(&env, &admin);
let attacker = Address::generate(&env);
let new_admin = Address::generate(&env);
let (_, client) = create_pool(&env);
let (usdc, _, _) = create_usdc(&env, &admin);

client.init(&admin, &usdc_address);
fund_pool(&usdc_admin, &pool_addr, 1_000);
client.init(&admin, &usdc);
client.set_admin(&attacker, &new_admin);
}

let payments = vec![&env, (dev1.clone(), 300), (dev2.clone(), 500)];
client.batch_distribute(&admin, &payments);
#[test]
#[should_panic(expected = "revenue pool not initialized")]
fn balance_before_init_panics() {
let env = Env::default();
let (_, client) = create_pool(&env);
client.balance();
}

assert_eq!(usdc_client.balance(&pool_addr), 200);
assert_eq!(usdc_client.balance(&dev1), 300);
assert_eq!(usdc_client.balance(&dev2), 500);
#[test]
fn distribute_negative_panics() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let developer = Address::generate(&env);
let (_, client) = create_pool(&env);
let (usdc, _, _) = create_usdc(&env, &admin);

client.init(&admin, &usdc);
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
client.distribute(&admin, &developer, &-1);
}));
assert!(result.is_err());
}

#[test]
#[should_panic(expected = "amount must be positive")]
fn batch_distribute_zero_panics() {
fn receive_payment_from_non_vault() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let dev1 = Address::generate(&env);
let dev2 = Address::generate(&env);
let (_, client) = create_pool(&env);
let (usdc_address, _, _) = create_usdc(&env, &admin);
let (usdc, _, _) = create_usdc(&env, &admin);

client.init(&admin, &usdc);
client.receive_payment(&admin, &250, &false);

let events = env.events().all();
assert!(!events.is_empty());
}

/// Full lifecycle test: init, get_admin, balance, distribute, receive_payment, set_admin.
#[test]
fn full_lifecycle() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let new_admin = Address::generate(&env);
let developer = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, usdc_client, usdc_admin) = create_usdc(&env, &admin);

// Init
client.init(&admin, &usdc_address);
assert_eq!(client.get_admin(), admin);

let payments = vec![&env, (dev1.clone(), 300), (dev2.clone(), 0)];
client.batch_distribute(&admin, &payments);
// Fund and check balance
fund_pool(&usdc_admin, &pool_addr, 1000);
assert_eq!(client.balance(), 1000);

// Distribute
client.distribute(&admin, &developer, &400);
assert_eq!(usdc_client.balance(&developer), 400);
assert_eq!(client.balance(), 600);

// Receive payment event
client.receive_payment(&admin, &100, &true);

// Set admin
client.set_admin(&admin, &new_admin);
assert_eq!(client.get_admin(), new_admin);

// New admin can distribute
client.distribute(&new_admin, &developer, &100);
assert_eq!(usdc_client.balance(&developer), 500);
assert_eq!(client.balance(), 500);
}

#[test]
#[should_panic(expected = "insufficient USDC balance")]
fn batch_distribute_insufficient_balance_panics() {
fn batch_distribute_success() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let dev1 = Address::generate(&env);
let dev2 = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, _, usdc_admin) = create_usdc(&env, &admin);
let (usdc_address, usdc_client, usdc_admin) = create_usdc(&env, &admin);

client.init(&admin, &usdc_address);
fund_pool(&usdc_admin, &pool_addr, 400);
fund_pool(&usdc_admin, &pool_addr, 1000);

let payments = vec![&env, (dev1.clone(), 300), (dev2.clone(), 200)];
let mut payments: Vec<(Address, i128)> = Vec::new(&env);
payments.push_back((dev1.clone(), 300_i128));
payments.push_back((dev2.clone(), 200_i128));
client.batch_distribute(&admin, &payments);

assert_eq!(usdc_client.balance(&dev1), 300);
assert_eq!(usdc_client.balance(&dev2), 200);
assert_eq!(client.balance(), 500);
}

#[test]
Expand All @@ -209,44 +267,50 @@ fn batch_distribute_unauthorized_panics() {
env.mock_all_auths();
let admin = Address::generate(&env);
let attacker = Address::generate(&env);
let dev1 = Address::generate(&env);
let dev = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, _, usdc_admin) = create_usdc(&env, &admin);

client.init(&admin, &usdc_address);
fund_pool(&usdc_admin, &pool_addr, 1000);
fund_pool(&usdc_admin, &pool_addr, 500);

let payments = vec![&env, (dev1.clone(), 300)];
let mut payments: Vec<(Address, i128)> = Vec::new(&env);
payments.push_back((dev.clone(), 100_i128));
client.batch_distribute(&attacker, &payments);
}

#[test]
fn get_admin_before_init_fails() {
#[should_panic(expected = "amount must be positive")]
fn batch_distribute_zero_amount_panics() {
let env = Env::default();
let (_, client) = create_pool(&env);
let result = client.try_get_admin();
assert!(result.is_err(), "expected error when pool not initialized");
}
env.mock_all_auths();
let admin = Address::generate(&env);
let dev = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, _, usdc_admin) = create_usdc(&env, &admin);

#[test]
fn balance_before_init_fails() {
let env = Env::default();
let (_, client) = create_pool(&env);
let result = client.try_balance();
assert!(result.is_err(), "expected error when pool not initialized");
client.init(&admin, &usdc_address);
fund_pool(&usdc_admin, &pool_addr, 500);

let mut payments: Vec<(Address, i128)> = Vec::new(&env);
payments.push_back((dev.clone(), 0_i128));
client.batch_distribute(&admin, &payments);
}

#[test]
fn set_admin_unauthorized_fails() {
#[should_panic(expected = "insufficient USDC balance")]
fn batch_distribute_insufficient_balance_panics() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let intruder = Address::generate(&env);
let new_admin = Address::generate(&env);
let (_, client) = create_pool(&env);
let (usdc, _, _) = create_usdc(&env, &admin);
let dev = Address::generate(&env);
let (pool_addr, client) = create_pool(&env);
let (usdc_address, _, usdc_admin) = create_usdc(&env, &admin);

client.init(&admin, &usdc);
let result = client.try_set_admin(&intruder, &new_admin);
assert!(result.is_err(), "expected error for unauthorized set_admin");
client.init(&admin, &usdc_address);
fund_pool(&usdc_admin, &pool_addr, 50);

let mut payments: Vec<(Address, i128)> = Vec::new(&env);
payments.push_back((dev.clone(), 100_i128));
client.batch_distribute(&admin, &payments);
}
Loading
Loading