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

Wrong `resolveDispute` logic, ambigous operation when resolving a dispute, lead to wrong transfer allocation of award

Summary

Wrong resolveDispute logic, ambigous operation when resolving a dispute, lead to wrong transfer allocation of award

Vulnerability Details

In a typical dispute resolution process, the main subject of consideration is usually the seller, as they are the party whose service or product is being evaluated and potentially disputed by the buyer. Therefore, it would be more logical and common for the resolveDispute function to distribute the tokens in favor of the seller, rather than the buyer.

resolveDispute function parameter the buyerAward, this is very ambiguous. I think this parameter should be the sellerAward. Following information based on Line 111, uint256 totalFee = buyerAward + i_arbiterFee; it only make sense if the buyerAward is actually sellerAward.

I mean, how can buyer get an Award, while they are the one who put their money to the Escrow contract. Award should goes to party doing the work, in this case seller.

The totalFee is buyerAward plus arbiterFee doesn't make sense. It will make sense if the totalFee is sellerAward + arbiterFee.

This issue is not only of swapped terminology of buyerAward and sellerAward, more on that, the effect is seller will get the rest of balance after transfering to buyer & arbiter (Line 127) as, this can make ambiguous operation.

File: Escrow.sol
109: function resolveDispute(uint256 buyerAward) external onlyArbiter nonReentrant inState(State.Disputed) {
110: uint256 tokenBalance = i_tokenContract.balanceOf(address(this));
111: uint256 totalFee = buyerAward + i_arbiterFee; // Reverts on overflow
112: if (totalFee > tokenBalance) {
113: revert Escrow__TotalFeeExceedsBalance(tokenBalance, totalFee);
114: }
115:
116: s_state = State.Resolved;
117: emit Resolved(i_buyer, i_seller);
118:
119: if (buyerAward > 0) {
120: i_tokenContract.safeTransfer(i_buyer, buyerAward);
121: }
122: if (i_arbiterFee > 0) {
123: i_tokenContract.safeTransfer(i_arbiter, i_arbiterFee);
124: }
125: tokenBalance = i_tokenContract.balanceOf(address(this));
126: if (tokenBalance > 0) {
127: i_tokenContract.safeTransfer(i_seller, tokenBalance);
128: }
129: }

In such a case, the buyerAward parameter in the resolveDispute function should represent the amount of tokens that will be awarded to the seller as compensation for their service or product. The function would then focus to transfer the tokens to the seller first, and any remaining token balance after deducting the i_arbiterFee would be returned to the buyer.

By doing so, the function aligns with the standard dispute resolution approach, where the seller is the main focus, and the outcome of the resolution process determines the appropriate compensation for their work.

Impact

Ambigous operation when resolving a dispute, lead to wrong transfer allocation of funds

Tools Used

Manual audit

Recommendations

Swap the buyerAward to sellerAward, and swap the order of transfer, the 'refund' to buyer should be on the last transfer after deducting from sellerAward and arbiterFee.

function resolveDispute(uint256 sellerAward) external onlyArbiter nonReentrant inState(State.Disputed) {
uint256 tokenBalance = i_tokenContract.balanceOf(address(this));
uint256 totalFee = sellerAward + i_arbiterFee; // Reverts on overflow
if (totalFee > tokenBalance) {
revert Escrow__TotalFeeExceedsBalance(tokenBalance, totalFee);
}
s_state = State.Resolved;
emit Resolved(i_buyer, i_seller);
if (sellerAward > 0) {
i_tokenContract.safeTransfer(i_seller, sellerAward);
}
if (i_arbiterFee > 0) {
i_tokenContract.safeTransfer(i_arbiter, i_arbiterFee);
}
tokenBalance = i_tokenContract.balanceOf(address(this));
if (tokenBalance > 0) {
i_tokenContract.safeTransfer(i_buyer, tokenBalance);
}
}

But if this resolveDispute parameter input is for sending token to buyer, the terminology should be refundToBuyerAmount to avoid the ambiguous

Support

FAQs

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