Funds can get stuck in the Escrow contract if a dispute is initiated and either the Arbiter or the Seller gets blacklisted in the contract of the price token
When a dispute is initiated, currently, the only path to resolve it is when the arbiters call the Escrow:resolveDispute()
.
The arbiter has control over how many tokens will be refunded to the buyer (if any).
The resolveDispute()
will attempt to transfer the refunds to the buyer (if any), the fees to the arbiter, and the remaining tokens in the contract's balance will be sent to the seller.
The problem is that the resolveDispue()
is pushing the tokens from the contract to the accounts, if the prize token (i_tokenContract
) is a token like USDC
or USDT
that has blacklisted functionalities it opens the risk of blocking intentionally or by accident all the funds in the Escrow contract when a dispute is initiated.
Additionally, there is a check to prevent the totalFee
(which is the sum of the refunded amount to the buyer + the arbiter's fees) is not greater than the tokenBalance, which means, that after refunding the buyer and paying the arbiter's fees will be left over at least 1 wei in the contract, and this 1 wei will be attempted to be transferred to the seller!
Suppose the below scenarios:
The dispute was opened by the buyer, and as per the Arbiter's judgment the buyer is right and it should get refunded X amount of tokens (it could be a 100% of the contract's token balance).
After a long back-and-forth discussion, the seller just doesn't accept the arbiter's judgment.
The arbiter has decided to resolve the dispute and refund the X amount to the buyer.
The seller, instead of accepting the arbiter's judgment, blacklists his address in the underlying prize token.
When the arbiter attempts to resolve the dispute, the tx will be reverted because the seller's address is blacklisted in the prize token.
As a result, even if the arbiter has taken a decision to resolve the dispute, the dispute won't be able to be resolved and the funds will be stuck in the Escrow contract.
The arbiter's address gets blacklisted in the prize token contract (i_tokenContract) and a dispute is opened.
If the arbiter's address is blacklisted & there are any arbiter fees (i_arbiterFee), the dispute won't be able to be resolved and the funds will be stuck in the Escrow contract
There are a number of widely used ERC20 tokens that have blacklists (e.g. USDC, USDT). Reference
Manual Audit
Implement a pull pattern instead of a push pattern to distribute the tokens when disputes are resolved
Allow each user to claim individually their respective portion of the prize
In this way, if one of the user's addresses is blacklisted it won't affect the process to resolve the dispute, and the rest of the users won't be affected to claim their respective tokens
Create a new mapping to keep track of the amount of funds that each entity will be allowed to claim
In the resolveDispute(), instead of sendings the tokens to the accounts, update the new claimAmounts
mapping, so the users can later claim their respective tokens
Create a function to allow the users to claim their funds
Optionally, you could allow the users to specify the address where they want to receive their funds
Create a function to allow the users to claim their funds
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.