When an ask offer is partially filled with a bid order, and then it is settled with amount of points less than used amount of points, the maker's collateral will be locked. Then when the taker closes his bid, he gets a portion of the maker's collateral. So, some part of the maker's collateral will stuck in the protocol and no one is able to withdraw them.
Suppose Alice (maker) creates an ask offer to buy 1000 points for $1000 with collateral rate 12000 (equivalent to 120%). So, she deposits $1200.
Bob (taker) places a bid order to buy 700 points from Alice.
Then the market updates and TGE happens where tokenPerPoint = 1e18
. So, it is expected that Alice provides 700 * 1e18
marketPlaceInfo.tokenAddress
to keep her promise.
Suppose Alice has only 500e18
marketPlaceInfo.tokenAddress
.
Then, Alice or the protocol owner can call the function settleAskMaker
to settle this trade.
Alice is reasonable to not call this function, because she owns only 500 points while she promised 700 points, so her collateral will be locked in the protocol and she can not withdraw it during the settlement. Moreover, if she calls this function she has to provide some marketPlaceInfo.tokenAddress
as well.
So, the owner will call this function to settle this trade (as Alice did not settle it). Please note that whether Alice or owner calls this function does not change the validity of this report.
Thus, the body of the following if-clause will not be executed during settlement (_settledPoints < usedPoints
):
https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L276
Then Bob calls the function closeBidTaker
. Since offerInfo.usedPoints > offerInfo.settledPoints
(as you remember usedPoints
= 700 and settledPoints
is 0 up to 500 based on whether settleAsMaker
is called by the owner or Alice). So, the body of the following if-clause will be executed:
https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L152
Since the offer status is settled, we will have:
https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L162-L174
Then we will have $840 as the amount of Alice's collateral that will be paid to Bob as RemainingCash
.
https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L178-L189
The issue is that Alice deposited $1200 while the amount of collateral dedicated to Bob is only $840, it means that 1200 - 840 = $360
is stuck in the protocol and unreachable. Moreover, Alice can not withdraw them as her offer is settled.
Note that Bob places a bid order by depositing $700, and he is receiving $840.
Note that as explained above Alice will not call the function settleAsMaker
because she does not want to lose marketPlaceInfo.tokenAddress
. So, there will be no marketPlaceInfo.tokenAddress
for Bob as well.
Please note that this bug is not at all related to the owner.
The following test implements the exact scenario explained above.
The output is:
Stuck of collateral in the protocol without being able to withdraw them.
Maker should be able to withdraw part of her collateral that is not used even after the settlement.
Valid medium, there are disruptions to the ability to take market actions. The following functions will be disrupted without the possibiliy of reaching settlement, since the respective offers cannot be created/listed regardless of mode when transferring collateral token required to the CapitalPool contract or when refunding token from user to capital pool during relisting. So withdrawal is not an issue - `createOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L96-L102) - `listOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L355-L362) - `relistOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L515-L521) - `createTaker()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L831-L836) I believe medium severity is appropriate although the likelihood is high and impact is medium (only some level of disruption i.e. FOT tokens not supported and no funds at risk)
Valid high, in settleAskTaker/settleAskMaker, if the original offer maker performs a partial final settlement, the existing checks [here](https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L356-L358) and [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/DeliveryPlace.sol#L230-L232) will cause an revert when attempting to complete a full settlement, resulting in their collateral being locked and requiring a rescue from the admin. To note, although examples in the documentation implies settlement in a single click, it is not stated that partial settlements are not allowed, so I believe it is a valid user flow.
Valid high, in settleAskTaker/settleAskMaker, if the original offer maker performs a partial final settlement, the existing checks [here](https://github.com/Cyfrin/2024-08-tadle/blob/main/src/core/DeliveryPlace.sol#L356-L358) and [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/DeliveryPlace.sol#L230-L232) will cause an revert when attempting to complete a full settlement, resulting in their collateral being locked and requiring a rescue from the admin. To note, although examples in the documentation implies settlement in a single click, it is not stated that partial settlements are not allowed, so I believe it is a valid user flow.
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.