Skip to content

Commit

Permalink
Use a library for reward collection
Browse files Browse the repository at this point in the history
To ease the cost of deploying a new collector contract, we should
decrease the size of its code, but the tradeoff is that we need to do an
extra `delegate_call` to the library when collecting rewards.
  • Loading branch information
enriquefynn committed Nov 23, 2023
1 parent 9c19d1d commit 359216c
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 25 deletions.
67 changes: 50 additions & 17 deletions src/FeeRewardsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,29 @@ pragma solidity ^0.8.13;

import "@openzeppelin/contracts/access/Ownable.sol";

contract RewardsCollector is Ownable {
library CalculateAndSendRewards {
// Fee denominator, if `feeNominator = 500`,
// the tax is 500/10000 = 5/100 = 5%.
uint32 public constant FEE_DENOMINATOR = 10000;
event CollectedReward(
address withdrawalCredential,
uint256 withdrawalFee,
address owner,
uint256 ownerFee
);

// 1 - fee % will go to the user in this address.
address public withdrawalCredential;

// Nominator of the fee.
uint32 public feeNominator;

// Fee denominator, if `feeNominator = 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 {
function calculateRewards(
uint32 feeNominator,
address owner,
address withdrawalCredential
) public {
uint256 ownerAmount = (address(this).balance * feeNominator) /
FEE_DENOMINATOR;
uint256 returnedAmount = address(this).balance - ownerAmount;
require(
ownerAmount != 0 || returnedAmount != 0,
"Nothing to distribute"
);
address owner = owner();
emit CollectedReward(
withdrawalCredential,
returnedAmount,
Expand All @@ -47,13 +40,53 @@ contract RewardsCollector is Ownable {
}("");
require(sent, "Failed to send Ether back to withdrawal credential");
}
}

contract RewardsCollector {
event CollectedReward(
address withdrawalCredential,
uint256 withdrawalFee,
address owner,
uint256 ownerFee
);

// 1 - fee % will go to the user in this address.
address public withdrawalCredential;

// Nominator of the fee.
uint32 public feeNominator;

// This is the contract that created the `RewardsCollector`.
// Do not use owner here because this contract is going to be
// created multiple times for each `withdrawal credential` and
// we don't need any function for the ownership except when changing
// the fee.
address public parentContract;

uint32 public constant FEE_DENOMINATOR = 10000;

// Allow receiving MEV and other rewards.
receive() external payable {}

function collectRewards() public payable {
CalculateAndSendRewards.calculateRewards(
feeNominator,
parentContract,
withdrawalCredential
);
}

constructor(address _withdrawalCredential, uint32 _feeNominator) {
withdrawalCredential = _withdrawalCredential;
feeNominator = _feeNominator;
parentContract = msg.sender;
}

function changeFee(uint32 _newFee) public onlyOwner {
function changeFee(uint32 _newFee) public {
require(
msg.sender == parentContract,
"ChangeFee not called from parent contract"
);
feeNominator = _newFee;
}
}
Expand Down
11 changes: 3 additions & 8 deletions test/FeeRewardsManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ contract ReentrantAttack {
}
}

contract ChangeOwnerContract {
fallback() external payable {
RewardsCollector(payable(msg.sender)).transferOwnership(address(0x200));
}
}

contract WithdrawalContract {
fallback() external payable {}
}
Expand Down Expand Up @@ -47,7 +41,7 @@ contract FeeRewardsTest is Test {
// derived address has the parent's as owner
assertEq(
address(feeRewardsManager),
RewardsCollector(payable(addr)).owner()
RewardsCollector(payable(addr)).parentContract()
);

uint256 amountInContract = address(addr).balance;
Expand Down Expand Up @@ -145,7 +139,8 @@ contract FeeRewardsTest is Test {
rewards
);
uint256 chorusAmount = (address(collector).balance *
uint256(collector.feeNominator())) / collector.FEE_DENOMINATOR();
uint256(collector.feeNominator())) /
CalculateAndSendRewards.FEE_DENOMINATOR;
uint256 withdrawalCredentialsAmount = address(collector).balance -
chorusAmount;
uint256 chorusBalanceBefore = address(feeRewardsManager).balance;
Expand Down

0 comments on commit 359216c

Please sign in to comment.