40,000 USDC
View results
Submission Details
Severity: medium
Valid

If there is no Arbiter, a buyer cannot get back his funds if the seller becomes malicious

Summary

Once the buyer locks in his funds in the escrow contract, only the Arbiter can get it back for him if the seller becomes malicious. If there is no Arbiter, the funds are essentially locked in the contract.

Vulnerability Details

When creating an escrow, the buyer has to deposit some funds into the escrow contract. In the best-case scenario whereby the seller does his job well, the buyer calls confirmReceipt() to send the funds to the seller.

function confirmReceipt() external onlyBuyer inState(State.Created) {
s_state = State.Confirmed;
emit Confirmed(i_seller);
i_tokenContract.safeTransfer(i_seller, i_tokenContract.balanceOf(address(this)));
}

However, the protocol knows that not everything can be perfect, and that's why if there's a problem with the seller, the buyer will call initiateDispute() so that the Arbiter can solve the dispute by calling resolveDispute() and splitting the funds accordingly.

function initiateDispute() external onlyBuyerOrSeller inState(State.Created) {
if (i_arbiter == address(0)) revert Escrow__DisputeRequiresArbiter();
s_state = State.Disputed;
emit Disputed(msg.sender);
}

There can be cases where there is no Arbiter involved. In such cases, if there is a dispute because the seller is not doing his job properly or goes MIA, then the buyer will lose all the funds that he deposited for the job because there is no way of withdrawing the funds deposited by himself.

Impact

Buyer's funds are locked and he will lose all the funds deposited for the job.

Tools Used

Manual review

Recommendations

Recommend setting a time limit when creating an escrow. After the time limit, the buyer is allowed to withdraw the funds. However, this way also introduces another issue where the buyer can choose not to pay the seller and wait until the time limit is over to withdraw the funds, but that is still better than having the funds stuck in the contract.

The best way is to simply require an Arbiter for all escrow so that these types of things won't happen. The arbiter, if not chosen, is defaulted to the protocol (CodeHawks) with a default fee.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.