Due to an oversight in the implementation of listOffer(address,uint256,uint256)
, an attacker may manipulate the refund process to steal funds from the protocol.
The listOffer(address,uint256,uint256)
function accepts a collateralRate
argument from the caller and only ever validates that this is equal to the collateralRate
of the existing offer for the case where the offerSettleType
is OfferSettleType.TURBO
:
This means that the caller may specify a higher collateralRate
than the original offer when the offerSettleType
is OfferSettleType.PROTECTED
, and have this successfully serialized into state.
We should note that when pulling the tokens of a
PROTECTED
offer, these are only pulled at the originalcollateralRate
cached in storage, and not the maliciously manipulated value:uint256 transferAmount = OfferLibraries.getDepositAmount(offerInfo.offerType,offerInfo.collateralRate, /// @audit uses_original_collateral_rate_amount,true,Math.Rounding.Ceil);
Consequently, when the attacker cancels both offers to redeem their refunds, they can receive refunds at a higher collateralization rate than their initial deposit.
This is demonstrated in the proof of concept exploit below.
Manipulated collateralRate
can be exploited to accrue undue refunds at the expense of other protocol users to the point of insolvency.
Manual Review
Unconditionally validate the collateralRate
is expected, regardless of the offerSettleType
:
Valid high severity, because the collateral rate utilized when creating an offer is stale and retrieved from a previously set collateral rate, it allows possible manipilation of refund amounts using an inflated collateral rate to drain funds from the CapitalPool contract
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.