Closed howlbot-integration[bot] closed 2 months ago
The credit seller pays for swap fees
It works as intended.
In your example, the borrower should pay credits of netCashAmountIn * 110% = 995e6 * 1.1
.
After that, the swapFee
(= 4975000) will be taken from netCashAmountIn
.
hansfriese marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-06-size/blob/8850e25fb088898e9cf86f9be1c401ad155bea86/src/libraries/AccountingLibrary.sol#L294
Vulnerability details
Impact
Wrong calculations causes the borrowers to owe more credit than necessary
Proof of Concept
Whenever a user has a borrow offer, lenders can use
buyCreditMarket()
to lend to that user. Then, there are different calculations taking place to compute the amount of credit the borrower owes, the amount of cash the lender should give out as well as the fees associated with that whole deal.The lender can specify the exact amount of cash he wants to give and from it, the credit the borrower will owe is computed. The amount of cash specified, however, is not necessarily equal to the amount of cash the borrower will receive as there are fees associated with the deal. There are 2 types of fees in this deal - a fragmentation fee and a swap fee. The fragmentation fee is paid whenever a credit position used for a borrow is split. That fee is paid by whoever split the position so in our case, that would be the lender as he is the one lending out (the active party). The swap fee is paid by the cash receiver, this is the borrower in our case.
Here is one of the most important things in that whole lending/borrowing functionality:
The lender has specified the amount of cash he wants to spend for the deal. From that, we compute the
creditAmountOut
and thefees
usinggetCreditAmountOut()
. Here is that function:We will focus our attention on the
else if
block, that is the code responsible for split positions (that will pretty much always be the case we end up in if the lender specifiesexactAmountIn
as true and the borrow happens with a credit position instead of doing a simple borrow).Here is that
else if
block:Since the lender split the position, there is now the
fragmentationFee
involved. There is also aswapFee
. Let's do some calculations to see what the computed values would be. Let's imagine thatcashAmountIn
is 1000e6 andratePerTenor
is 1e17 (10%). ThefragmentationFee
is 5e6 and theswapFee
is 0.005e18 (both according to the deployment scripts). Then, we have the following computations:netCashAmountIn
will equal $1000e6 - 5e6 = 995e6$creditAmountOut
is equal $995e6 * 1.1e18 / 1e18 = 1094500000$fees
are equal to $4975000 + 5e6 = 9975000$ (tenor is a year in our example so the swap fee will be equal to the yearly swap fee)If we compare that to the
creditAmountOut
we computed earlier, we can see that thecreditAmountOut
computed by the system is larger than the actual one it should be by 497500 (equal to around 0.50\$). The borrower has to pay 0.50\$ more than what should actually be required. While that is not a significant amount, that would occur every single time whenever a user lends to a borrower withexactAmountIn
as true leading to tens and hundreds of thousands of losses for borrowers overtime. Furthermore, the amount would be larger for larger deals, thus this issue should be of high severity.Now, to explain why is that.
creditAmountOut
is calculated usingnetCashAmountIn
however we can see thatnetCashAmountIn
does not actually include the swap fee which is also deducted from the borrower's received cash. If we calculate thenetCashAmountIn
as follows:Then, we would properly calculate the amount owed (I am aware that the swap fee is calculated using the
netCashAmountIn
so that creates a little bit of a paradox with the current code, it would need some refactoring).Paste the following POC into
BuyCreditMarket.t.sol
(simple POC to show thatcreditAmountOut
is equal to my calculations, the rest if for you to properly calculate and see the inaccuracy):Tools Used
Manual Review
Recommended Mitigation Steps
Refactor the code based on my last few lines of the issue before the POC.
Assessed type
Math