Open
This is the test written by protocol team inside test/integration/ProxyFactoryTest.t.sol file.
I am going to modify it to show the effect when the malicious sponser will not transfer the funds and owner tries to distribute the funds.
function testSucceedsIfAllConditionsMet()
public
setUpContestForJasonAndSentJpycv2Token(organizer)
{
assertEq(MockERC20(jpycv2Address).balanceOf(user1), 0 ether);
assertEq(MockERC20(jpycv2Address).balanceOf(stadiumAddress), 0 ether);
bytes32 randomId_ = keccak256(abi.encode("Jason", "001"));
bytes memory data = createData();
vm.warp(16 days);
vm.startPrank(factoryAdmin);
proxyFactory.deployProxyAndDistributeByOwner(
organizer,
randomId_,
address(distributor),
data
);
vm.stopPrank();
assertEq(MockERC20(jpycv2Address).balanceOf(user1), 9500 ether);
assertEq(MockERC20(jpycv2Address).balanceOf(stadiumAddress), 500 ether);
}
Here in this modifier, I have comment out the code of sponsor transfering the funds to proxy contract.
modifier setUpContestForJasonAndSentJpycv2Token(address _organizer) {
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)
);
_;
}
Now if you run the test using this command forge test --mt testSucceedsIfAllConditionsMet -vvv
You will see this error message;
│ ├─ [28306] → new <Unknown>@0x717a630f36795235Aa9Bd5bf6DF42c431d2875FD
│ │ └─ ← 140 bytes of code
│ ├─ [11077] 0x717a630f36795235Aa9Bd5bf6DF42c431d2875FD::distribute(MockERC20: [0x90193C961A926261B756D1E5bb255e67ff9498A1], [0x000000000000000000000000000000000000000E], [9500], 0x)
│ │ ├─ [8287] Distributor::distribute(MockERC20: [0x90193C961A926261B756D1E5bb255e67ff9498A1], [0x000000000000000000000000000000000000000E], [9500], 0x) [delegatecall]
│ │ │ ├─ [2575] ProxyFactory::whitelistedTokens(MockERC20: [0x90193C961A926261B756D1E5bb255e67ff9498A1]) [staticcall]
│ │ │ │ └─ ← true
│ │ │ ├─ [2563] MockERC20::balanceOf(0x717a630f36795235Aa9Bd5bf6DF42c431d2875FD) [staticcall]
│ │ │ │ └─ ← 0
│ │ │ └─ ← "Distributor__NoTokenToDistribute()"
│ │ └─ ← "Distributor__NoTokenToDistribute()"
│ └─ ← "ProxyFactory__DelegateCallFailed()"
└─ ← "ProxyFactory__DelegateCallFailed()"
View Mitigation
+ import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol";
function setContest(
address organizer,
bytes32 contestId,
uint256 closeTime,
address implementation,
+ address token,
+ uint256 reward
) public onlyOwner {
if (organizer == address(0) || implementation == address(0))
revert ProxyFactory__NoZeroAddress();
if (
closeTime > block.timestamp + MAX_CONTEST_PERIOD ||
closeTime < block.timestamp
) {
revert ProxyFactory__CloseTimeNotInRange();
}
bytes32 salt = _calculateSalt(organizer, contestId, implementation);
if (saltToCloseTime[salt] != 0)
revert ProxyFactory__ContestIsAlreadyRegistered();
+ address proxyAddress = getProxyAddress(salt, implementation);
+ if (reward == 0 || IERC20(token).balanceOf(proxyAddress) < reward) {
+ revert ProxyFactory__NotEnoughBalance();
+ }
saltToCloseTime[salt] = closeTime;
emit SetContest(organizer, contestId, closeTime, implementation);
}