Max amount for repay function does not have correct formula
Summary
If amountCall parameter in repayInternal in BlueBerryBank.sol is set to type(uint256).max then the max amount of borrow tokens are sent back to the user. The formula for calculating the max number of borrow tokens is incorrect and can lead to a revert of the tx.
Vulnerability Detail
This is the code in question:
function repayInternal(
uint256 positionId,
address token,
uint256 amountCall
) internal returns (uint256, uint256) {
Bank storage bank = banks[token];
Position storage pos = positions[positionId];
uint256 totalShare = bank.totalShare;
uint256 totalDebt = bank.totalDebt;
uint256 oldShare = pos.debtShareOf[token];
uint256 oldDebt = (oldShare * totalDebt).divCeil(totalShare);
if (amountCall == type(uint256).max) {
// STENT this amount is not correct, it should involve a more complicated equation or just have the amount given by the balance of borrowToken in the spell
amountCall = oldDebt;
}
amountCall = doERC20TransferIn(token, amountCall);
uint256 paid = doRepay(token, amountCall);
if (paid > oldDebt) revert REPAY_EXCEEDS_DEBT(paid, oldDebt); // prevent share overflow attack
uint256 lessShare = paid == oldDebt
? oldShare
: (paid * totalShare) / totalDebt;
bank.totalShare = totalShare - lessShare;
uint256 newShare = oldShare - lessShare;
pos.debtShareOf[token] = newShare;
if (newShare == 0) {
pos.debtMap &= ~(1 << uint256(bank.index));
}
return (paid, lessShare);
}
The formula for oldDebt is not the max amount of borrow tokens that can be transferred. The bank tries to transfer borrow tokens from the Ichi spell to the bank (in the case that the Ichi spell is used to open and close positions). The spell got the tokens from the Ichi vault and then did a swap on Uniswap, thus the amount of borrow tokens that the spell has is dependent on the inner workings of Ichi and Uniswap, which the formula for oldDebt does not take into account.
Example test where tx is reverted with ERC20: transfer amount exceeds balance:
Any smart contract that depends on the assumption that amountCall == type(uint256).max means all borrow tokens are returned to Compound may break, up to the mercy of inner workings of Uni and Ichi. If there are more borrow tokens than the formula suggests then everything works fine, but otherwise the tx will revert.
stent
medium
Max amount for repay function does not have correct formula
Summary
If
amountCall
parameter inrepayInternal
in BlueBerryBank.sol is set totype(uint256).max
then the max amount of borrow tokens are sent back to the user. The formula for calculating the max number of borrow tokens is incorrect and can lead to a revert of the tx.Vulnerability Detail
This is the code in question:
The formula for
oldDebt
is not the max amount of borrow tokens that can be transferred. The bank tries to transfer borrow tokens from the Ichi spell to the bank (in the case that the Ichi spell is used to open and close positions). The spell got the tokens from the Ichi vault and then did a swap on Uniswap, thus the amount of borrow tokens that the spell has is dependent on the inner workings of Ichi and Uniswap, which the formula foroldDebt
does not take into account.Example test where tx is reverted with
ERC20: transfer amount exceeds balance
:Impact
Any smart contract that depends on the assumption that
amountCall == type(uint256).max
means all borrow tokens are returned to Compound may break, up to the mercy of inner workings of Uni and Ichi. If there are more borrow tokens than the formula suggests then everything works fine, but otherwise the tx will revert.Code Snippet
https://github.com/sherlock-audit/2023-02-blueberry/blob/main/contracts/BlueBerryBank.sol#L770
Tool used
Manual Review
Recommendation
Set the max amount to
min(oldDebt, borrowToken.balanceOf(ichiSpell)
Duplicate of #14