Skip to content

Commit daa140f

Browse files
authored
Merge pull request #601 from Sundriveauto/feat/depositor-yield-query
feat(contracts): add get_depositor_yield() view function to LendingPool
2 parents 6ede1f3 + 56a56fe commit daa140f

3 files changed

Lines changed: 72 additions & 1 deletion

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ coverage
1212
*.log
1313
.idea
1414
create_issues.sh
15-
.claude
15+
.claude
16+
.kiro/

contracts/lending_pool/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,28 @@ impl LendingPool {
479479
Ok(())
480480
}
481481

482+
/// Returns `(shares, current_asset_value)` for `provider` in the `token` pool.
483+
///
484+
/// Net yield = `current_asset_value - original_deposit`. Since original
485+
/// deposit amounts are not stored per-depositor, callers derive yield by
486+
/// comparing `current_asset_value` against their own recorded cost basis.
487+
pub fn get_depositor_yield(env: Env, provider: Address, token: Address) -> (i128, i128) {
488+
let shares = Self::read_shares(&env, &provider, &token);
489+
if shares == 0 {
490+
return (0, 0);
491+
}
492+
let cur_total_shares = Self::total_shares(&env, &token);
493+
if cur_total_shares == 0 {
494+
return (shares, 0);
495+
}
496+
let asset_value = Self::calc_assets_to_redeem(
497+
shares,
498+
Self::read_pool_balance(&env, &token),
499+
cur_total_shares,
500+
);
501+
(shares, asset_value)
502+
}
503+
482504
/// Underlying asset value of `provider`'s LP shares (principal + yield).
483505
pub fn get_deposit(env: Env, provider: Address, token: Address) -> i128 {
484506
let shares = Self::read_shares(&env, &provider, &token);

contracts/lending_pool/src/test.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,3 +831,51 @@ fn test_get_admin_returns_initialized_admin() {
831831

832832
assert_eq!(pool_client.get_admin(), admin);
833833
}
834+
835+
#[test]
836+
fn test_get_depositor_yield_no_deposit() {
837+
let env = Env::default();
838+
env.mock_all_auths();
839+
840+
let admin = Address::generate(&env);
841+
let (token_id, _, _) = create_token_contract(&env, &admin);
842+
let pool_id = env.register(LendingPool, ());
843+
let pool_client = LendingPoolClient::new(&env, &pool_id);
844+
pool_client.initialize(&admin);
845+
846+
let provider = Address::generate(&env);
847+
assert_eq!(
848+
pool_client.get_depositor_yield(&provider, &token_id),
849+
(0, 0)
850+
);
851+
}
852+
853+
#[test]
854+
fn test_get_depositor_yield_reflects_accrued_interest() {
855+
let env = Env::default();
856+
env.mock_all_auths();
857+
858+
let admin = Address::generate(&env);
859+
let (token_id, stellar_asset_client, _) = create_token_contract(&env, &admin);
860+
let pool_id = env.register(LendingPool, ());
861+
let pool_client = LendingPoolClient::new(&env, &pool_id);
862+
pool_client.initialize(&admin);
863+
pool_client.set_withdrawal_cooldown(&0);
864+
865+
let provider = Address::generate(&env);
866+
stellar_asset_client.mint(&provider, &1000);
867+
pool_client.deposit(&provider, &token_id, &1000);
868+
869+
// Before any yield: asset_value == deposit amount.
870+
let (shares, asset_value) = pool_client.get_depositor_yield(&provider, &token_id);
871+
assert_eq!(shares, 1000);
872+
assert_eq!(asset_value, 1000);
873+
874+
// Simulate interest repaid into the pool (increases pool balance without
875+
// minting new shares, so each share is now worth more).
876+
stellar_asset_client.mint(&pool_id, &200);
877+
878+
let (shares2, asset_value2) = pool_client.get_depositor_yield(&provider, &token_id);
879+
assert_eq!(shares2, 1000);
880+
assert_eq!(asset_value2, 1200); // 1000 shares * 1200 assets / 1000 total_shares
881+
}

0 commit comments

Comments
 (0)