The function calculates the debtShares corresponding to the amount which the user want to borrow by a round-down calculation. This could lead to the vulnerability that when user borrow many times and try to payback in 1 turn, their transaction can be revert because of the following condition:
function payback(uint256 debt, address owner) public override returns (uint256) {
...
if (debt > convertToDebt(_debtShares[owner])) {
revert BorrowingVault__payback_moreThanMax();
}
Attack scenario
We shall assume the state of vault as follows:
debtShareSupply = 100
totalDebt = 200
minAmount = 1
The whole strategy as follows:
Bob call borrow(3, bob_address, bob_address)
He will get3 * 100 / 200 = 1 debtShare
Bob call borrow(3, bob_address, bob_address)
He will get3 * (100+1) / (200+3) = 1 debtShare
Bob call payback(6, bob_address), function payBack get convertToDebt(2) = 2 * (200 + 6) / (100 + 2) = 4
Then it will be revert in this function since (debt > convertToDebt(_debtShares[owner])) (6 > 4)
Recommendation
Modify function convertDebtToShares() as follows:
function convertDebtToShares(uint256 debt) public view override returns (uint256 shares) {
return _convertDebtToShares(debt, Math.Rounding.Up);
}
Title
Wrong implmentation of function BorrowingVault.convertDebtToShares
Affected smart contract
https://github.com/Fujicracy/fuji-v2/blob/1b939ec84af137db430fc2aa1b4c6f15e5254003/packages/protocol/src/vaults/borrowing/BorrowingVault.sol#L175
Description
Function
BorrowingVault.borrow()
is implemented as follows:The function calculates the debtShares corresponding to the amount which the user want to borrow by a round-down calculation. This could lead to the vulnerability that when user borrow many times and try to payback in 1 turn, their transaction can be revert because of the following condition:
Attack scenario
We shall assume the state of vault as follows:
The whole strategy as follows:
borrow(3, bob_address, bob_address)
He will get3 * 100 / 200 = 1
debtShareborrow(3, bob_address, bob_address)
He will get3 * (100+1) / (200+3) = 1
debtSharepayback(6, bob_address)
, functionpayBack
getconvertToDebt(2) = 2 * (200 + 6) / (100 + 2) = 4
Then it will be revert in this function since(debt > convertToDebt(_debtShares[owner]))
(6 > 4)Recommendation
Modify function
convertDebtToShares()
as follows: