Spare Canvas Sheep
Medium
The implicit assumption about token decimals will cause protocol unable to mint UBI from reserve balance through function GoodDollarExpansionController#mintUBIFromReserveBalance()
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
- The DAO creates a pool
- The pool has a reserve asset token having decimals lower than 18
- 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
- The protocol can not mint UBI from reserve balance increases by function
mintUBIFromReserveBalance
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)
Consider scaling the variable contractReserveBalance
to be equal to exchange.reserveBalance
decimals