M-16: Repayments and liquidations can be forced to revert by an attacker that repays miniscule amount of shares
Comments
Both V3Vault.repay() and V3Vault.liquidate() have a safety check that will cause a revert when a caller repays too much (specifically when the repayment exceeds the loan debt owed). A malicious user can frontrun any liquidate/repay call by repaying the loan by 1 share. This in turn leads to the repay() and liquidate() functions reverting.
Mitigation
PR #14, #30
To mitigate this, the Vault included the following major changes:
V3Vault.liquidate() no longer enforces a check that the caller explicitly acknowledges the amount of debt shares they are liquidating. This ensures that a third-party user can't frontrun any liquidation call with a small repayment via V3Vault.repay() and revert the liquidation.
V3Vault._repay() will now max out the repayment amount to the current shares owed. This ensures that repayers do not overpay the loan. In addition, the repayment will still succeed if too much is repaid.
Modified LeverageTransformer.leverageDown() such that whatever leftover tokens are left after V3Vault.repay() will be transferred back to the params.recipient.
Minor changes include:
Modifying V3Vault.repay() to return the number of assets and shares used in repayment. This is helpful in cases of LeverageTransformer.leverageDown() where the transformer must calculate how many leftover tokens it has to repay the original caller.
V3Vault._withdraw() adds a balance withdrawal check that prevents a withdrawer from withdrawing more lent tokens than they own. This check validates that the balanceOf(owner) is not less than the requested shares to borrow and if so adjusts the amount of lent tokens withdrawn to match the balance of the owner. This guarantees that the lender will receive tokens and not have their call revert if they requested too many tokens.
In summary, both the repay and liquidation functionality now support variable repayments that handle cases where too much is repaid/liquidated. This involves adding checks to see if too much was repaid. If too much was repaid, the Vault adjusts the payment owed to match the max owed. This guarantees that repayers can't frontrun liquidator/repay calls.
Lines of code
Vulnerability details
C4 issue
M-16: Repayments and liquidations can be forced to revert by an attacker that repays miniscule amount of shares
Comments
Both V3Vault.repay() and V3Vault.liquidate() have a safety check that will cause a revert when a caller repays too much (specifically when the repayment exceeds the loan debt owed). A malicious user can frontrun any liquidate/repay call by repaying the loan by 1 share. This in turn leads to the repay() and liquidate() functions reverting.
Mitigation
PR #14, #30
To mitigate this, the Vault included the following major changes:
Minor changes include:
In summary, both the repay and liquidation functionality now support variable repayments that handle cases where too much is repaid/liquidated. This involves adding checks to see if too much was repaid. If too much was repaid, the Vault adjusts the payment owed to match the max owed. This guarantees that repayers can't frontrun liquidator/repay calls.
Conclusion
LGTM