40,000 USDC
View results
Submission Details
Severity: gas

Include a fuzz test for arbitrary balances > `price`

Summary

The code base currently lacks any tests that account for the possibility of the Escrow contract holding extra tokens beyond the known i_price.

Vulnerability Details

There is nothing preventing the Escrow contract from holding extra tokens, but all of the tests assume it simply holds the i_price amount. It can hold extra tokens as early as construction, given that this requirement in the constructor does not enforce equality:

if (tokenContract.balanceOf(address(this)) < price) revert Escrow__MustDeployWithTokenBalance();

Impact

The test coverage is incomplete (no vulnerability, only informational).

Tools Used

Manual review.

Recommendations

Add a test like this one:

function testResolveDisputeFuzz(uint256 award, uint256 extraBalance) public escrowDeployed {
uint256 escrowInitialBalance = ERC20Mock(address(i_tokenContract)).balanceOf(address(escrow));
vm.assume(extraBalance <= type(uint256).max - escrowInitialBalance);
// Contract holds arbitrary extra balance beyond the preset `PRICE`.
ERC20Mock(address(i_tokenContract)).mint(address(escrow), extraBalance);
uint256 escrowStartingBalance = ERC20Mock(address(i_tokenContract)).balanceOf(address(escrow));
// Arbiter grants arbitrary award to the buyer.
vm.assume(award <= type(uint256).max - ARBITER_FEE);
uint256 totalFee = ARBITER_FEE + award;
vm.assume(totalFee <= escrowStartingBalance);
// Seller should receive balance minus fees.
uint256 sellerAward = escrowStartingBalance - totalFee;
uint256 buyerStartingBalance = ERC20Mock(address(i_tokenContract)).balanceOf(BUYER);
uint256 sellerStartingBalance = ERC20Mock(address(i_tokenContract)).balanceOf(SELLER);
uint256 arbiterStartingBalance = ERC20Mock(address(i_tokenContract)).balanceOf(ARBITER);
vm.prank(BUYER);
escrow.initiateDispute();
vm.prank(ARBITER);
escrow.resolveDispute(award);
assertEq(ERC20Mock(address(i_tokenContract)).balanceOf(address(escrow)), 0);
assertEq(ERC20Mock(address(i_tokenContract)).balanceOf(BUYER), buyerStartingBalance + award);
assertEq(ERC20Mock(address(i_tokenContract)).balanceOf(SELLER), sellerStartingBalance + sellerAward);
assertEq(ERC20Mock(address(i_tokenContract)).balanceOf(ARBITER), arbiterStartingBalance + ARBITER_FEE);
}

Support

FAQs

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