Summary
The CreditDelegationBranch::depositCreditForMarket
function assumes transferred token amounts match amount
parameter. Fee-on-transfer tokens (e.g., STA, PAXG) will cause collateral under-accounting.
Vulnerability Details
Affected Code:
function depositCreditForMarket(...) {
IERC20(collateralAddr).safeTransferFrom(msg.sender, address(this), amount);
UD60x18 amountX18 = collateral.convertTokenAmountToUd60x18(amount);
market.depositCredit(collateralAddr, amountX18);
}
Exploit Scenario:
-
Attacker deposits 100 STA (which charges 5% fee)
-
Protocol receives 95 STA but records 100 STA
-
Protocol becomes undercollateralized
Proof of Concept:
function testFeeOnTransferExploit() public {
address FEE_TOKEN = 0xSTA...;
uint256 DEPOSIT_AMOUNT = 100e18;
deal(FEE_TOKEN, perpsEngine, DEPOSIT_AMOUNT);
vm.prank(perpsEngine);
creditDelegation.depositCreditForMarket(MARKET_ID, FEE_TOKEN, DEPOSIT_AMOUNT);
assertEq(IERC20(FEE_TOKEN).balanceOf(address(creditDelegation)), 95e18);
assertEq(market.creditDeposits(FEE_TOKEN), 100e18);
}
Impact
Direct Fund Loss: LPs over-redeem based on inflated balances
Protocol Insolvency: Total collateral < reported value
Tools Used
Manual analysis
Foundry test simulating fee-on-transfer
Recommendations
uint256 balanceBefore = IERC20(collateralAddr).balanceOf(address(this));
IERC20(collateralAddr).safeTransferFrom(msg.sender, address(this), amount);
uint256 received = IERC20(collateralAddr).balanceOf(address(this)) - balanceBefore;
UD60x18 amountX18 = collateral.convertTokenAmountToUd60x18(received);