Skip to content

Commit

Permalink
Feature/variable fee input (#11)
Browse files Browse the repository at this point in the history
* fix(splitter): fix some minor bugs and add invariant testing

* feat(readme): add new audit link and new contract addresses

* feat(fees): add variable fees

* feat(readme): add new audit link and new contract addresses
  • Loading branch information
goncaloMagalhaes authored Mar 6, 2024
1 parent 65b873d commit 6f64c3f
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 200 deletions.
5 changes: 2 additions & 3 deletions script/SplitterDeployer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import "../src/Splitter.sol";

contract SplitterDeployer is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
uint256 deployerPrivateKey = uint256(vm.envBytes32("PRIVATE_KEY"));
uint256 gasCap = 50_000;
uint256 maxFee = 15_00;
uint256 fee = 10_00;
address owner = vm.envAddress("SPLITTER_OWNER");
address payable feeRecipient = payable(vm.envAddress("SPLITTER_FEE_RECIPIENT"));

vm.startBroadcast(deployerPrivateKey);
new Splitter{ salt: "immunefi" }(gasCap, maxFee, fee, owner, feeRecipient);
new Splitter{ salt: "immunefi" }(gasCap, maxFee, owner, feeRecipient);
vm.stopBroadcast();
}
}
50 changes: 10 additions & 40 deletions src/Splitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import { IERC20 } from "openzeppelin-contracts/interfaces/IERC20.sol";
import { SafeERC20 } from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import { Ownable } from "openzeppelin-contracts/access/Ownable.sol";
import { ReentrancyGuard } from "openzeppelin-contracts/security/ReentrancyGuard.sol";
import { Withdrawable } from "./Withdrawable.sol";

/**
* @title Splitter
* @author Immunefi
*/
contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
contract Splitter is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;

struct ERC20Payment {
Expand All @@ -20,7 +19,6 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
}

event FeeRecipientChanged(address prevFeeRecipient, address newFeeRecipient);
event FeeChanged(uint256 prevFee, uint256 newFee);
event PayWhitehat(
address indexed from,
bytes32 indexed referenceId,
Expand All @@ -31,45 +29,21 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
uint256 fee
);

uint256 public fee;
uint256 public constant FEE_BASIS = 100_00;
uint256 public immutable maxFee;
uint256 public immutable gasCap;
address payable public feeRecipient;

constructor(uint256 _gasCap, uint256 _maxFee, uint256 _fee, address _owner, address payable _feeRecipient) {
constructor(uint256 _gasCap, uint256 _maxFee, address _owner, address payable _feeRecipient) {
require(_maxFee <= FEE_BASIS, "Splitter: maxFee must be below FEE_BASIS");
maxFee = _maxFee;

gasCap = _gasCap;

_setFee(_fee);

_changeFeeRecipient(_feeRecipient);

_transferOwnership(_owner);
}

/**
* @notice internal set fee
* @param newFee value of the new fee. Must be less than maxFee
*/
function _setFee(uint256 newFee) internal {
require(newFee <= maxFee, "Splitter: fee must be below maxFee");

emit FeeChanged(fee, newFee);
fee = newFee;
}

/**
* @notice set fee
* @dev only callable by owner
* @param newFee value of the new fee
*/
function setFee(uint256 newFee) public onlyOwner {
_setFee(newFee);
}

/**
* @notice internal change fee recipient
* @param newFeeRecipient address of new fee recipient
Expand Down Expand Up @@ -101,16 +75,19 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
* @param payout The payout of tokens/token amounts to whitehat
* @param nativeTokenAmt The payout of native Ether amount to whitehat
* @param gas The amount of gas to forward to the whitehat to mitigate gas griefing
* @param fee The fee to be paid to the fee recipient
*/
function payWhitehat(
bytes32 referenceId,
address payable wh,
ERC20Payment[] calldata payout,
uint256 nativeTokenAmt,
uint256 gas
) public payable nonReentrant {
uint256 gas,
uint256 fee
) external payable nonReentrant {
require(wh != address(0), "Splitter: Whitehat address cannot be null");
require(gas <= gasCap, "Splitter: Gas greater than max allowed");
require(fee <= maxFee, "Splitter: Fee greater than max allowed");

for (uint256 i = 0; i < payout.length; i++) {
uint256 feeAmount = (payout[i].amount * fee) / FEE_BASIS;
Expand All @@ -119,7 +96,7 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
}

if (nativeTokenAmt > 0) {
_payWhitehatNative(wh, nativeTokenAmt, gas);
_payWhitehatNative(wh, nativeTokenAmt, gas, fee);
} else if (msg.value > 0) {
// must refund msg.sender
_refundCaller(msg.value);
Expand All @@ -135,8 +112,9 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
* @param wh whitehat address
* @param nativeTokenAmt The payout of native Ether amount to whitehat
* @param gas The amount of gas to forward to the whitehat to mitigate gas griefing
* @param fee The fee to be paid to the fee recipient
*/
function _payWhitehatNative(address payable wh, uint256 nativeTokenAmt, uint256 gas) internal {
function _payWhitehatNative(address payable wh, uint256 nativeTokenAmt, uint256 gas, uint256 fee) internal {
uint256 feeAmount = (nativeTokenAmt * fee) / FEE_BASIS;
if (feeAmount > 0) {
// feeRecipient is trusted, we can skip this check
Expand Down Expand Up @@ -164,12 +142,4 @@ contract Splitter is Ownable, Withdrawable, ReentrancyGuard {
(bool success, ) = msg.sender.call{ value: amount }("");

Check warning on line 142 in src/Splitter.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use low level calls
require(success, "Splitter: Failed to refund to msg.sender");
}

/**
* @notice Withdraw asset ERC20 or ETH
* @param assetAddress Asset to be withdrawn.
*/
function withdrawERC20ETH(address assetAddress) public override onlyOwner {
super.withdrawERC20ETH(assetAddress);
}
}
35 changes: 0 additions & 35 deletions src/Withdrawable.sol

This file was deleted.

2 changes: 1 addition & 1 deletion test/foundry/Splitter.invariants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract SplitterInvariantsTest is Test {
feeRecipient = payable(vm.addr(2));
gasCap = 500_000;

splitter = new Splitter(gasCap, 1_500, 1_000, owner, feeRecipient);
splitter = new Splitter(gasCap, 1_500, owner, feeRecipient);

handler = new Handler(splitter);

Expand Down
Loading

0 comments on commit 6f64c3f

Please sign in to comment.