Closed code423n4 closed 2 years ago
Not a bug, this is exactly how the contract is meant to work.
Borrowers pay an immediate fee when taking out a loan, and they pay interest when paying off the loan. The protocol takes a cut of both.
The comment is in a section of code that only calculates what the initial distribution of funds should look like, at the moment the loan is established.
downgrading to QA and duplicating with wardens QA report of #97
This is a documentation / comments issue
Lines of code
https://github.com/code-423n4/2022-04-abranft/blob/main/contracts/NFTPair.sol#L271-L315 https://github.com/code-423n4/2022-04-abranft/blob/main/contracts/NFTPair.sol#L505-L543 https://github.com/code-423n4/2022-04-abranft/blob/main/test/NFTPair.test.ts#L296-L304
Vulnerability details
Impact
In the tests you can find a comment describing the fee structure of the contract:
barrylyndon from the Abracadabra team confirmed that the comment is still valid in a DM I sent him.
But, looking at the code you can see that the fees are actually collected and distributed a little differently:
The lender pays and receives the correct amount. But, the borrower doesn't only pay the open fee but also pays another fee to the protocol derived from the interest they pay. The protocol receives fees twice from both the lender and the borrower. The borrower isn't supposed to pay any tho. They lose part of their funds so I rate this issue as high.
Proof of Concept
I will show it for
NFTPair
but the same thing is valid forNFTPairWithOracle
since it's pretty much the same contract.In L290-L293 the total amount of shares and fees are determined:
In L295-L302 we can see that the contract receives the correct amount:
The lender is supposed to receive the
openFeeShare
so you subtract it from the total amount of shares you take from them. TheprotocolFeeShare
is paid by the borrower.The
totalShare - openFeeShare
is then sent to the borrower in L304-L305:When the borrower repays the loan, they pay the principal, interest, and a protocol fee that is derived from the interest as seen in L515-L524:
The contract keeps the
feeShare
for itself and transfers the rest back to the lender, L526-L539:Thus, the protocol received fees twice. Once from the lender when
_lend()
is called and once from the borrower whenrepay()
is called.Tools Used
none
Recommended Mitigation Steps
When repaying, the contract shouldn't take any fees as described in the test's comment.