Skip to content

Latest commit

 

History

History
69 lines (47 loc) · 2.68 KB

File metadata and controls

69 lines (47 loc) · 2.68 KB

Spare Canvas Sheep

Medium

Unable to mint UBI from reserve balance

Summary

The implicit assumption about token decimals will cause protocol unable to mint UBI from reserve balance through function GoodDollarExpansionController#mintUBIFromReserveBalance()

Root Cause

The function GoodDollarExpansionController#mintUBIFromReserveBalance() is used to mint UBI by taking the reserve balance increases as interest. But in function logic, the contract reserve balance is not explicitly scaled to 18 decimals when the exchange.reserveBalance is in 18 decimals. https://github.com/sherlock-audit/2024-10-mento-update/blob/main/mento-core/contracts/goodDollar/GoodDollarExpansionController.sol#L157-L158 This can cause the function to always revert if the reserve asset's decimals is lower than 18 due to arithmetic underflow at line 158

Internal pre-conditions

  1. The DAO creates a pool

External pre-conditions

  1. The pool has a reserve asset token having decimals lower than 18

Attack Path

  1. The DAO creates a pool with params
            reserveAsset: address(reserveToken),
            tokenAddress: address(token),
            tokenSupply: 7 * 1e9 * 1e18,
            reserveBalance: 200_000 * 1e18,
            reserveRatio: 0.2 * 1e8, // 20%
            exitContribution: 0.1 * 1e8 // 10%

in which, the reserveToken has decimals 8 (an arbitrary value < 18) 2. The reserve asset balance of address reserve increases

Impact

  • The protocol can not mint UBI from reserve balance increases by function mintUBIFromReserveBalance

PoC

Modify the test test_mintUBIFromReserveBalance_whenAdditionalReserveBalanceIsLargerThan0_shouldMintAndEmit() as below:

    function test_mintUBIFromReserveBalance_whenAdditionalReserveBalanceIsLargerThan0_shouldMintAndEmit() public {
        // Mock the `reserveToken` to have 8 decimals
        deployCodeTo("ERC20SetDecimals", abi.encode("cUSD", "cUSD",address(this), 1, 8), address(reserveToken));

        uint256 additionalReserveBalance = 1000e8; // the increased amount of token balance

        // pool.reserveBalance = 200_000 * 1e18  <= 18 decimals --> scale down to proper token balance
        uint balance = (pool.reserveBalance / 1e10);
        deal(address(reserveToken), reserveAddress, balance + additionalReserveBalance);

        vm.expectRevert();
        expansionController.mintUBIFromReserveBalance(exchangeId);
    }

Run the test and console shows:

[PASS] test_mintUBIFromReserveBalance_whenAdditionalReserveBalanceIsLargerThan0_shouldMintAndEmit() (gas: 368618)

Mitigation

Consider scaling the variable contractReserveBalance to be equal to exchange.reserveBalance decimals