Skip to content

Latest commit

 

History

History
129 lines (101 loc) · 4.05 KB

036.md

File metadata and controls

129 lines (101 loc) · 4.05 KB

Low Tangerine Cod

High

abond holder can steal from other abond holders

Summary

user1 can use other user2 power(ethBacked) to withdraw more eth than he suppose to when redeeming abond tokens

Root Cause

redeemYields allows to specify arbitrary user for redeeming

    function redeemYields(
-->        address user,
        uint128 aBondAmount
    ) public returns (uint256) {
        // Call redeemYields function in Borrow Library
        return (
            BorrowLib.redeemYields(
-->                user,
                aBondAmount,
                address(usda),
                address(abond),
                address(treasury),
                address(this)
            )
        );
    }

contracts/Core_logic/borrowing.sol#L318

Later there is call withdrawFromExternalProtocol with user and not msg.sender

    function redeemYields(
        address user,
        uint128 aBondAmount,
        address usdaAddress,
        address abondAddress,
        address treasuryAddress,
        address borrow
    ) public returns (uint256) {
...
        uint256 withdrawAmount = treasury.withdrawFromExternalProtocol(user,aBondAmount);
...
    }

contracts/lib/BorrowLib.sol#L1029

Later the amount to withdraw from external protocol based on that user power/stake

    function withdrawFromIonicByUser(
        address user,
-->        uint128 aBondAmount
    ) internal nonReentrant returns (uint256) {
        uint256 currentExchangeRate = ionic.exchangeRateCurrent();
        uint256 currentCumulativeRate = _calculateCumulativeRate(currentExchangeRate, Protocol.Ionic);

        State memory userState = abond.userStates(user);
-->        uint128 depositedAmount = (aBondAmount * userState.ethBacked) / PRECISION;
        uint256 normalizedAmount = (depositedAmount * CUMULATIVE_PRECISION) / userState.cumulativeRate;

        //withdraw amount
        uint256 amount = (currentCumulativeRate * normalizedAmount) / CUMULATIVE_PRECISION;
        // withdraw from ionic
        ionic.redeemUnderlying(amount);

        protocolDeposit[Protocol.Ionic].totalCreditedTokens = ionic.balanceOf(address(this));
        protocolDeposit[Protocol.Ionic].exchangeRate = currentExchangeRate;
        // convert weth to eth
        WETH.withdraw(amount);
        return amount;
    }

Core_logic/Treasury.sol#L711

Also backed eth stays the same for that account due to the fact that only from msg.sender account ethBacked is being deducted. https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/lib/BorrowLib.sol#L1032

So, a user can create two accounts and exploit this issue to withdraw more funds from the protocol, essentially stealing from other bondholders.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. create 2 account.
  2. Use the account with highest eth backed(staked) as address user in redeemYields
  3. redeemYields with lowest backed eth then redeem with highest backed eth

Impact

  1. Abond holder can steal from other abond holders.
  2. Due to the fact that they redeem more ionic tokens than they should, there might be no enough ionic tokens for liquidations to happen

PoC

No response

Mitigation

    function redeemYields(
-        address user,
        uint128 aBondAmount
    ) public returns (uint256) {
        // Call redeemYields function in Borrow Library
        return (
            BorrowLib.redeemYields(
-                user,
+                msg.sender,
                aBondAmount,
                address(usda),
                address(abond),
                address(treasury),
                address(this)
            )
        );
    }