Platform: Code4rena
Start Date: 28/06/2022
Pot Size: $25,000 USDC
Total HM: 14
Participants: 50
Period: 4 days
Judge: GalloDaSballo
Total Solo HM: 7
Id: 141
League: ETH
Rank: 6/50
Findings: 2
Award: $2,148.10
🌟 Selected for report: 0
🚀 Solo Findings: 0
1074.0464 USDC - $1,074.05
function sweepInterest() external override { if (msg.sender != admin ) { revert SenderNotAdmin(msg.sender); } //Total balance of Treasury => Note + CNote Balance, Exp memory exRate = Exp({mantissa: cnote.exchangeRateStored()}); //used stored interest rates in determining amount to sweep //underflow impossible uint noteDiff = sub_(note.totalSupply(), note.balanceOf(address(this))); //Note deficit in Accountant uint cNoteBal = cnote.balanceOf(address(this)); //current cNote Balance uint cNoteAmt = mul_(cNoteBal, exRate); // cNote Balance converted to Note require(cNoteAmt >= noteDiff, "AccountantDelegate::sweepInterest:Error calculating interest to sweep"); uint amtToSweep = sub_(cNoteAmt, noteDiff); // amount to sweep in Note, uint cNoteToSweep = div_(amtToSweep, exRate); // amount of cNote to sweep = amtToSweep(Note) / exRate cNoteToSweep = (cNoteToSweep > cNoteBal) ? cNoteBal : cNoteToSweep; bool success = cnote.transfer(treasury, amtToSweep); if (!success) { revert SweepError(treasury , amtToSweep); //handles if transfer of tokens is not successful } TreasuryInterface Treas = TreasuryInterface(treasury); Treas.redeem(address(cnote),amtToSweep); require(cnote.balanceOf(treasury) == 0, "AccountantDelegate::sweepInterestError"); }
L101 will revert when there is more than 0 of cNote in treasury's balance.
The attacker can send 1 wei of cnote to treasury and sweepInterest()
will malfunction.
Remove L101.
#0 - GalloDaSballo
2022-08-16T17:21:35Z
Dup of #28
function sweepInterest() external override { if (msg.sender != admin ) { revert SenderNotAdmin(msg.sender); } //Total balance of Treasury => Note + CNote Balance, Exp memory exRate = Exp({mantissa: cnote.exchangeRateStored()}); //used stored interest rates in determining amount to sweep //underflow impossible uint noteDiff = sub_(note.totalSupply(), note.balanceOf(address(this))); //Note deficit in Accountant uint cNoteBal = cnote.balanceOf(address(this)); //current cNote Balance uint cNoteAmt = mul_(cNoteBal, exRate); // cNote Balance converted to Note require(cNoteAmt >= noteDiff, "AccountantDelegate::sweepInterest:Error calculating interest to sweep"); uint amtToSweep = sub_(cNoteAmt, noteDiff); // amount to sweep in Note, uint cNoteToSweep = div_(amtToSweep, exRate); // amount of cNote to sweep = amtToSweep(Note) / exRate cNoteToSweep = (cNoteToSweep > cNoteBal) ? cNoteBal : cNoteToSweep; bool success = cnote.transfer(treasury, amtToSweep); if (!success) { revert SweepError(treasury , amtToSweep); //handles if transfer of tokens is not successful } TreasuryInterface Treas = TreasuryInterface(treasury); Treas.redeem(address(cnote),amtToSweep); require(cnote.balanceOf(treasury) == 0, "AccountantDelegate::sweepInterestError"); }
In the context, cNoteToSweep
represents the interest earnings in cNote.
However, the cNoteToSweep
is not used when transferring cNote
to the treasury at L93, instead, amtToSweep
is used.
As a result, when exRate
> 1, more cNote
than expected will be transferred to the treasury, and this will lead to a shortage of cNote
for the accountant, further leading to AccountantSupplyError
when repayBorrow
in cNote
.
1,000,000e18
note1,000,000e18
noteexRate
= 1.1e18sweepInterest()
:noteDiff
= 2,000,000e18cNoteAmt
= 2,200,000e18amtToSweep
= 200,000e18cNoteToSweep
= ~181,818e18 (181818181818181818181818)cNoteBal.balanceOf(accountant)
= 2,000,000e18 - 200,000e18 = 1,800,000e18repayBorrow()
to repay 1,100,000e18
note:accountant.redeemMarket(1,100,000e18)
cNoteBal.balanceOf(accountant)
= 1,800,000e18 - 1,000,000e18 = 700,000e18repayBorrow()
to repay 1,100,000e18
note, the transaction will revert with AccountantSupplyError
, Bob was forced to continue paying interests.Change from amtToSweep
to cNoteToSweep
in L93
#0 - nivasan1
2022-07-04T19:12:12Z
duplicate of #11
#1 - GalloDaSballo
2022-08-16T17:24:45Z
Dup of #11