You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Contracts] LendingPool share accounting uses live token balance, making it manipulable by direct transfers and loan flows #2
lending_pool/src/lib.rs computes total_assets for both minting (total_assets_before in deposit) and redemption (calc_assets_to_redeem in redeem_shares/get_deposit/get_share_price) from read_pool_balance, the raw TokenClient::balance of the contract. loan_manager approve_loan transfers tokens out of the pool and repayments/seized collateral transfer them back in, so the share price swings with outstanding loans and anyone can inflate it by transferring tokens to the pool address, decoupling shares from tracked TotalDeposits.
Acceptance criteria
Define and document whether share value should track tracked principal+realized yield or raw balance, and make minting and redemption use one consistent accounting source
Ensure direct token transfers to the contract cannot arbitrarily change existing holders' redeemable value
Add tests covering deposit/redeem while loans are outstanding and after an unsolicited direct transfer
Reconcile TotalDeposits adjustments in redeem_shares (currently subtracts assets_to_return, which can drift from principal)
Hi, I’m interested in this issue. I have experience developing and auditing DeFi lending protocols, particularly around share accounting, pool solvency, and asset-liability reconciliation.
I can investigate the current lending pool accounting model and implement a consistent valuation mechanism so deposits, redemptions, and share pricing are derived from a single source of truth. I’ll address the issue where outstanding loans and unsolicited token transfers can distort share value, reconcile TotalDeposits accounting during redemptions, and ensure redeemable value accurately reflects the intended economic model.
I’ll also add comprehensive tests covering deposits and redemptions with active loans, loan repayment scenarios, and direct token transfers to the pool contract to verify share pricing remains correct and resistant to manipulation. The implementation will be thoroughly documented to clarify the chosen accounting model and its security implications.
Hi, I'd like to work on this issue.
The root problem is that total_assets — used identically by total_assets_before in deposit, and by calc_assets_to_redeem in redeem_shares/get_deposit/get_share_price — is read straight from read_pool_balance, the contract's live token balance. That balance moves for two reasons that have nothing to do with depositors' actual claims:
Direct transfer manipulation — anyone can send tokens straight to the pool address outside of deposit(), inflating the raw balance and therefore the share price, with no shares minted against it. This decouples share value from TotalDeposits and is the same mechanism behind the classic vault-inflation attack pattern seen elsewhere in DeFi.
Loan-flow swings — approve_loan moves tokens out of the pool to the borrower, and repayment/seized-collateral flows move them back in. Outstanding loan principal is a real claim the pool holds (a receivable), but raw-balance accounting treats it as if it simply vanished from the pool while the loan is outstanding, then reappears on repayment. That makes share price swing with loan activity in a way unrelated to actual gains or losses, and opens a window for depositing while loans are out (price artificially low) and redeeming after repayment (price restored) at other holders' expense — or the reverse, depending on direction.
The acceptance criteria frames the first deliverable as a decision to make explicit, not just a bug to patch: whether share value tracks principal + realized yield via an internal ledger, or stays balance-based with the manipulation vectors closed some other way (e.g. netting out a tracked outstanding-loan figure against raw balance). Given the bug description leans heavily on "decoupling shares from tracked TotalDeposits," I'd default to the ledger approach — total_assets computed as tracked principal plus realized/repaid interest, updated on explicit events (deposit, redemption, loan repayment), rather than read live from TokenClient::balance. That makes outstanding loan principal count as a pool asset regardless of where the tokens currently sit, and makes unsolicited direct transfers inert with respect to share price (they'd land in the contract without affecting accounting — whether that means "stuck" or "sweepable by admin" is a separate, smaller decision worth confirming).
Two things I'd want to settle with you before finalizing the implementation, since the issue intentionally leaves them open:
Should accrued but unrepaid loan interest count toward share price, or only interest once realized via repayment? This affects whether share price can still be gamed around loan accrual timing even after the fix.
For the TotalDeposits reconciliation point — currently redeem_shares subtracts assets_to_return (computed from the manipulable current price) from TotalDeposits, which can drift from actual principal outstanding. Once accounting moves off raw balance, I'd track principal and yield as separate ledger entries so redemption draws proportionally from both rather than subtracting a blended figure from a single bucket — but want to confirm that matches the intended model rather than assuming it.
Test plan: deposit/redeem sequences with loans outstanding (verifying price doesn't swing purely from disbursement/repayment), an unsolicited direct-transfer scenario verifying existing holders' redeemable value is unaffected, and a redemption test checking TotalDeposits stays consistent with actual remaining principal across multiple deposit/redeem cycles. Leaving the oracle and multi-asset rebalancing out per scope.
Activity
Awointa commentedon Jun 17, 2026
Hi, I’m interested in this issue. I have experience developing and auditing DeFi lending protocols, particularly around share accounting, pool solvency, and asset-liability reconciliation.
I can investigate the current lending pool accounting model and implement a consistent valuation mechanism so deposits, redemptions, and share pricing are derived from a single source of truth. I’ll address the issue where outstanding loans and unsolicited token transfers can distort share value, reconcile
TotalDepositsaccounting during redemptions, and ensure redeemable value accurately reflects the intended economic model.I’ll also add comprehensive tests covering deposits and redemptions with active loans, loan repayment scenarios, and direct token transfers to the pool contract to verify share pricing remains correct and resistant to manipulation. The implementation will be thoroughly documented to clarify the chosen accounting model and its security implications.
xeladev4 commentedon Jun 19, 2026
Hi, I'd like to work on this issue.
The root problem is that total_assets — used identically by total_assets_before in deposit, and by calc_assets_to_redeem in redeem_shares/get_deposit/get_share_price — is read straight from read_pool_balance, the contract's live token balance. That balance moves for two reasons that have nothing to do with depositors' actual claims:
Direct transfer manipulation — anyone can send tokens straight to the pool address outside of deposit(), inflating the raw balance and therefore the share price, with no shares minted against it. This decouples share value from TotalDeposits and is the same mechanism behind the classic vault-inflation attack pattern seen elsewhere in DeFi.
Loan-flow swings — approve_loan moves tokens out of the pool to the borrower, and repayment/seized-collateral flows move them back in. Outstanding loan principal is a real claim the pool holds (a receivable), but raw-balance accounting treats it as if it simply vanished from the pool while the loan is outstanding, then reappears on repayment. That makes share price swing with loan activity in a way unrelated to actual gains or losses, and opens a window for depositing while loans are out (price artificially low) and redeeming after repayment (price restored) at other holders' expense — or the reverse, depending on direction.
The acceptance criteria frames the first deliverable as a decision to make explicit, not just a bug to patch: whether share value tracks principal + realized yield via an internal ledger, or stays balance-based with the manipulation vectors closed some other way (e.g. netting out a tracked outstanding-loan figure against raw balance). Given the bug description leans heavily on "decoupling shares from tracked TotalDeposits," I'd default to the ledger approach — total_assets computed as tracked principal plus realized/repaid interest, updated on explicit events (deposit, redemption, loan repayment), rather than read live from TokenClient::balance. That makes outstanding loan principal count as a pool asset regardless of where the tokens currently sit, and makes unsolicited direct transfers inert with respect to share price (they'd land in the contract without affecting accounting — whether that means "stuck" or "sweepable by admin" is a separate, smaller decision worth confirming).
Two things I'd want to settle with you before finalizing the implementation, since the issue intentionally leaves them open:
Should accrued but unrepaid loan interest count toward share price, or only interest once realized via repayment? This affects whether share price can still be gamed around loan accrual timing even after the fix.
For the TotalDeposits reconciliation point — currently redeem_shares subtracts assets_to_return (computed from the manipulable current price) from TotalDeposits, which can drift from actual principal outstanding. Once accounting moves off raw balance, I'd track principal and yield as separate ledger entries so redemption draws proportionally from both rather than subtracting a blended figure from a single bucket — but want to confirm that matches the intended model rather than assuming it.
Test plan: deposit/redeem sequences with loans outstanding (verifying price doesn't swing purely from disbursement/repayment), an unsolicited direct-transfer scenario verifying existing holders' redeemable value is unaffected, and a redemption test checking TotalDeposits stays consistent with actual remaining principal across multiple deposit/redeem cycles. Leaving the oracle and multi-asset rebalancing out per scope.
grantfox-oss commentedon Jun 19, 2026
🦊 GrantFox — @xeladev4 has been assigned to this issue as part of the Official Campaign campaign!
Next steps:
Closes #2)Good luck! Track your progress on GrantFox.
fix(lending_pool): base share accounting on tracked managed assets, n…
fix(lending_pool): base share accounting on tracked managed assets, n…
grantfox-oss commentedon Jun 20, 2026
🎉 This issue has been marked as completed on GrantFox as part of the Official Campaign campaign!
@xeladev4's PR #36 was approved and merged by @ogazboiz.
🏆 @xeladev4: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (188 total points). Track your full progress on GrantFox.
👏 Great work, @xeladev4! Keep contributing to LabsCrypt.