Open c4-submissions opened 9 months ago
bytes032 marked the issue as high quality report
bytes032 marked the issue as primary issue
The finding is valid in that you cannot claim the surplus
GalloDaSballo (sponsor) confirmed
You could argue it requires being redeemed or liquidated, but I don't think that can be considered an external requirement since it's a normal behaviour
meet high: Assets can be stolen/lost/compromised directly (or indirectly if there is a valid attack path that does not have hand-wavy hypotheticals).
jhsagd76 marked the issue as satisfactory
jhsagd76 marked the issue as selected for report
Lines of code
https://github.com/code-423n4/2023-10-badger/blob/main/packages/contracts/contracts/LeverageMacroBase.sol#L398-L431
Vulnerability details
Impact
On a short explanation, leverage macros are contracts specifically made to interact with the eBTC system, with a leverage macro you can:
Everyone is free to make a call to one of the functions in LeverageMacroFactory and deploy a new copy of the reference implementation of LeverageMacro for self use.
While having an opened Cdp position, there is always a chance for your position to be fully redeemed or liquidated. In this two cases there will always be a surplus collateral left to the owner of the Cdp when:
Any surplus collateral is send to the CollSurplusPool, which can later be claimed by the owner of the Cdp. The only way for an owner to claim his surplus collateral is to call the function claimSurplusCollShares in borrowerOperations, which is the only entry point to the CollSurplusPool.
The problem here is that LeverageMacroReferences don't have build in feature to claim the surplus collateral from its fully redeemed or liquidated Cdps. In this case the only way for LeverageMacroReference to claim the surplus collateral is to make an arbitrary call to the function claimSurplusCollShares in borrowerOperations. However this isn't possible as the LeverageMacroReference ensures there aren't any arbitrary calls made to the system contracts.
As we can see In _doSwap the first thing the function does, is to call the internal function _ensureNotSystem which ensures that the arbitraty call isn't made to any of the system contracts. Duo to that the function _doSwap will revert when a LeverageMacroReference tries to make an arbitrary call to borrowerOperations.
Since there is no build in feature to claim the surplus collateral and LeverageMacroReference can't make an arbitrary call to borrowerOperations. Any surplus collateral owned by LeverageMacroReference can't be further claimed back and will be permanently stuck in CollSurplusPool.
Proof of Concept
Tools Used
Manual review.
Recommended Mitigation Steps
Allowing LeverageMacroReference to do an arbitrary call to one of the system contracts brings bigger risk. So l would say the best recommendation is to build a feature for the LeverageMacroReference to do a claim surplus operation in order to claim its surplus collateral from CollSurplusPool:
Assessed type
call/delegatecall