From 1a5d72ebfb88f9fc36349aa90b8e6db328f4ce8a Mon Sep 17 00:00:00 2001 From: sin3point14 Date: Fri, 24 Nov 2023 15:07:14 +0530 Subject: [PATCH] Another deletion for review on updated master --- src/FeeRewardsManager.sol | 134 ----------------------- test/FeeRewardsManager.t.sol | 204 ----------------------------------- 2 files changed, 338 deletions(-) diff --git a/src/FeeRewardsManager.sol b/src/FeeRewardsManager.sol index ca48a06..e69de29 100644 --- a/src/FeeRewardsManager.sol +++ b/src/FeeRewardsManager.sol @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.13; - -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract RewardsCollector is Ownable { - event CollectedReward( - address withdrawalCredential, - uint256 withdrawalFee, - address owner, - uint256 ownerFee - ); - - // 1 - fee % will go to the user in this address. - address public withdrawalCredential; - - // Fee's numerator. - uint32 public feeNumerator; - - // Fee denominator, if `feeNumerator = 500`, - // the tax is 500/10000 = 5/100 = 5%. - uint32 public constant FEE_DENOMINATOR = 10000; - - // Allow receiving MEV and other rewards. - receive() external payable {} - - function collectRewards() public payable { - uint256 ownerAmount = (address(this).balance * feeNumerator) / - FEE_DENOMINATOR; - uint256 returnedAmount = address(this).balance - ownerAmount; - require( - ownerAmount != 0 || returnedAmount != 0, - "Nothing to distribute" - ); - address owner = owner(); - emit CollectedReward( - withdrawalCredential, - returnedAmount, - owner, - ownerAmount - ); - // This can be used to call this contract again (reentrancy) - // but since all funds from this contract are used for the owner - payable(owner).transfer(ownerAmount); - (bool sent, ) = payable(withdrawalCredential).call{ - value: returnedAmount - }(""); - require(sent, "Failed to send Ether back to withdrawal credential"); - } - - constructor(address _withdrawalCredential, uint32 _feeNumerator) { - withdrawalCredential = _withdrawalCredential; - feeNumerator = _feeNumerator; - } - - function changeFee(uint32 _newFeeNumerator) public onlyOwner { - feeNumerator = _newFeeNumerator; - } -} - -contract FeeRewardsManager is Ownable { - uint32 public defaultFeeNumerator; - - constructor(uint32 _defaultFeeNumerator) { - defaultFeeNumerator = _defaultFeeNumerator; - } - - event ContractDeployed(address contractAddress, uint32 feeNumerator); - - function changeDefaultFee(uint32 _newFeeNumerator) public onlyOwner { - defaultFeeNumerator = _newFeeNumerator; - } - - function createFeeContract( - address _withdrawalCredential - ) public returns (address payable) { - bytes32 withdrawalCredentialBytes = bytes32( - uint256(uint160(_withdrawalCredential)) - ); - address addr = address( - // Uses CREATE2 opcode. - new RewardsCollector{salt: withdrawalCredentialBytes}( - _withdrawalCredential, - defaultFeeNumerator - ) - ); - emit ContractDeployed(addr, defaultFeeNumerator); - return payable(addr); - } - - function predictFeeContractAddress( - address _withdrawalCredential - ) public view returns (address) { - bytes memory bytecode = type(RewardsCollector).creationCode; - bytecode = abi.encodePacked( - bytecode, - abi.encode(_withdrawalCredential, defaultFeeNumerator) - ); - bytes32 withdrawalCredentialBytes = bytes32( - uint256(uint160(_withdrawalCredential)) - ); - bytes32 hash = keccak256( - abi.encodePacked( - bytes1(0xff), - address(this), - withdrawalCredentialBytes, - keccak256(bytecode) - ) - ); - return address(uint160(uint(hash))); - } - - function changeFee( - address payable _feeContract, - uint32 _newFee - ) public onlyOwner { - RewardsCollector(_feeContract).changeFee(_newFee); - } - - function batchCollectRewards( - address payable[] calldata feeAddresses - ) public { - for (uint32 i = 0; i < feeAddresses.length; ++i) { - RewardsCollector(feeAddresses[i]).collectRewards(); - } - } - - receive() external payable {} - - // Withdraws Eth from the manager contract. - function getEth(address addr) external onlyOwner { - payable(addr).transfer(address(this).balance); - } -} diff --git a/test/FeeRewardsManager.t.sol b/test/FeeRewardsManager.t.sol index a8da436..e69de29 100644 --- a/test/FeeRewardsManager.t.sol +++ b/test/FeeRewardsManager.t.sol @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import "../src/FeeRewardsManager.sol"; - -contract ReentrantAttack { - fallback() external payable { - RewardsCollector(payable(msg.sender)).collectRewards(); - } -} - -contract ChangeOwnerContract { - fallback() external payable { - RewardsCollector(payable(msg.sender)).transferOwnership(address(0x200)); - } -} - -contract WithdrawalContract { - fallback() external payable {} -} - -contract FeeRewardsTest is Test { - FeeRewardsManager public feeRewardsManager; - - function setUp() public { - feeRewardsManager = new FeeRewardsManager(2800); - } - - function testHappyPath() public { - address withdrawalCredential = address(100); - vm.deal(address(0), 10 ether); - address derivedAddr = feeRewardsManager.predictFeeContractAddress( - withdrawalCredential - ); - - vm.deal(derivedAddr, 10 ether); - - address payable addr = feeRewardsManager.createFeeContract( - withdrawalCredential - ); - - //derived address matches the function to get one. - assertEq(derivedAddr, addr); - - // derived address has the parent's as owner - assertEq( - address(feeRewardsManager), - RewardsCollector(payable(addr)).owner() - ); - - uint256 amountInContract = address(addr).balance; - - // We've got 10 ether in the contract. - assertEq(amountInContract, 10 ether); - - RewardsCollector(payable(addr)).collectRewards(); - - // User receives 72%. - assertEq(withdrawalCredential.balance, 7.2 ether); - - // We receive 28%. - assertEq(address(feeRewardsManager).balance, 2.8 ether); - - feeRewardsManager.getEth(address(101)); - - // We've got the ether. - assertEq(address(feeRewardsManager).balance, 0 ether); - assertEq(address(101).balance, 2.8 ether); - } - - function createWithdrawalSimulateRewards( - address withdrawalCredential, - uint reward - ) public returns (RewardsCollector) { - address payable addr = feeRewardsManager.createFeeContract( - withdrawalCredential - ); - addr.transfer(reward); - return RewardsCollector(payable(addr)); - } - - function testGetMultipleRewards() public { - address payable[] memory addrs = new address payable[](100); - for (uint256 i = 0; i < 100; ++i) { - addrs[i] = payable( - address( - createWithdrawalSimulateRewards( - address(uint160(i + 100)), - 10 ether - ) - ) - ); - } - feeRewardsManager.batchCollectRewards(addrs); - assertEq(address(feeRewardsManager).balance, 280 ether); - } - - function testChangeDefaultFee() public { - feeRewardsManager.changeDefaultFee(100); - assertEq(feeRewardsManager.defaultFeeNumerator(), 100); - - address addr = address( - createWithdrawalSimulateRewards(address(100), 10 ether) - ); - RewardsCollector(payable(addr)).collectRewards(); - assertEq(address(100).balance, 9.9 ether); - // We receive 1%. - assertEq(address(feeRewardsManager).balance, 0.1 ether); - } - - function testChangeFee() public { - address addr = address( - createWithdrawalSimulateRewards(address(100), 10 ether) - ); - feeRewardsManager.changeFee(payable(addr), 10000); - RewardsCollector(payable(addr)).collectRewards(); - assertEq(address(100).balance, 0 ether); - // We receive 100%. - assertEq(address(feeRewardsManager).balance, 10 ether); - } - - function testZeroRewards() public { - address addr = address( - createWithdrawalSimulateRewards(address(100), 0) - ); - vm.expectRevert("Nothing to distribute"); - RewardsCollector(payable(addr)).collectRewards(); - } - - function testFuzzyHappyPathNoContracts( - uint128 rewards, - address owner - ) public { - // Some smart contracts will revert when called, avoid them. - vm.assume(owner.code.length == 0); - // Avoid some precompiles. - vm.assume(owner > address(0x100)); - vm.assume(rewards > 10000); - vm.assume(rewards < 1e30); - vm.deal(address(this), rewards); - RewardsCollector collector = createWithdrawalSimulateRewards( - owner, - rewards - ); - uint256 chorusAmount = (address(collector).balance * - uint256(collector.feeNumerator())) / collector.FEE_DENOMINATOR(); - uint256 withdrawalCredentialsAmount = address(collector).balance - - chorusAmount; - uint256 chorusBalanceBefore = address(feeRewardsManager).balance; - uint256 withdrawalBalanceBefore = owner.balance; - collector.collectRewards(); - assertEq( - address(owner).balance, - withdrawalBalanceBefore + withdrawalCredentialsAmount - ); - assertEq( - address(feeRewardsManager).balance, - chorusBalanceBefore + chorusAmount - ); - } - - // Test calling `collectRewards` from a contract that calls `collectRewards` - // again, this will revert as the Ether is divided just to Chorus and the - // withdrawal credential. - function testReentrantAttack() public { - ReentrantAttack withdrawalCredentialContract = new ReentrantAttack(); - address addr = address( - createWithdrawalSimulateRewards( - address(withdrawalCredentialContract), - 10 ether - ) - ); - vm.expectRevert("Failed to send Ether back to withdrawal credential"); - RewardsCollector(payable(addr)).collectRewards(); - } - - function testSendToContractWithdrawalCredential() public { - WithdrawalContract withdrawalCredentialContract = new WithdrawalContract(); - address addr = address( - createWithdrawalSimulateRewards( - address(withdrawalCredentialContract), - 10 ether - ) - ); - RewardsCollector(payable(addr)).collectRewards(); - assertEq(address(feeRewardsManager).balance, 2.8 ether); - assertEq(address(withdrawalCredentialContract).balance, 7.2 ether); - } - - function testChangeOwnerWithContract() public { - WithdrawalContract withdrawalCredentialContract = new WithdrawalContract(); - address addr = address( - createWithdrawalSimulateRewards( - address(withdrawalCredentialContract), - 10 ether - ) - ); - RewardsCollector(payable(addr)).collectRewards(); - assertEq(address(feeRewardsManager).balance, 2.8 ether); - assertEq(address(withdrawalCredentialContract).balance, 7.2 ether); - } -}