Fast Khaki Raccoon
Medium
Removing leverage will often fail when the received pair LP token is insufficient
Upon removing leverage (LeverageManager::removeLeverage()
), a part of the whole flow is receiving a pod token and a paired LP token. Then, the paired LP token which is also the initially flashloaned token is used to repay the flashloan. However, a very common scenario that can occur is that the received paired LP token is insufficient and we have to convert some of our pod token for the paired token:
if (_pairedAmtReceived < _repayAmount) {
_podAmtRemaining = _acquireBorrowTokenForRepayment(_props, _posProps.pod, _d.token, _repayAmount - _pairedAmtReceived, _podAmtReceived, _podSwapAmtOutMin, _userProvidedDebtAmtMax);
}
There, if the user does not cover the whole amount necessary using his own tokens and the pod is of a self lending type, we have to do an extra step and that is to first convert into the paired token which is the shares token of the lending pair instead of the borrow token, and then we have to redeem the share token for the underlying borrowed/flashloaned token. For that, we use the following code:
_podAmtRemaining = _swapPodForBorrowToken(
_pod,
positionProps[_props.positionId].lendingPair,
_podAmtReceived,
IFraxlendPair(positionProps[_props.positionId].lendingPair).convertToShares(_borrowAmtNeededToSwap),
_podSwapAmtOutMin
);
IFraxlendPair(positionProps[_props.positionId].lendingPair).redeem(IERC20(positionProps[_props.positionId].lendingPair).balanceOf(address(this)), address(this), address(this));
Since _borrowAmtNeededToSwap
is the amount of flashloaned tokens we need to repay, we have to convert them into the share amount, for that we use convertToShares()
. The issue is that convertToShares()
rounds down (second param in toAssetShares()
:
function convertToShares(uint256 _assets) external view returns (uint256 _shares) {
_shares = toAssetShares(_assets, false, true);
}
This means that we might receive 1 less share than supposed to during the swap. Then, we will redeem those shares for the amount which also rounds down, causing us to receive 1 less token than supposed to. Despite this being a 1 wei difference, we have to repay the full flashloan which will simply revert as the tokens we received are insufficient.
No response
No response
- After receiving our pod tokens and paired LP tokens, we are 100 tokens short from repayment
- We are using a self-lending pod so we use
convertToShares()
to convert those tokens to their corresponding shares amount, we round down to 99 - We receive 99 shares which we redeem and we receive 99 tokens (or less if we round down again)
- Upon the repayment, we will revert as we are 1-2 tokens short:
IERC20(_d.token).safeTransfer(IFlashLoanSource(_getFlashSource(_props.positionId)).source(), _repayAmount);
Removing leverage will often revert due to a round down
No response
Round up instead