FeeDistributor

0x8b31f9892cc6f435ba07126a653c88a5aab9845d

Verification
Verified
0.8.20+commit.a1b79de6
Type
Contract
4,327 bytes
ABI entries
32
13 read · 9 write
License
none

Contract information

Address
0x8b31f9892cc6f435ba07126a653c88a5aab9845d
Chain
Robinhood Chain (4663)
Compiler
0.8.20+commit.a1b79de6
Optimization
Enabled
Creation tx
0x0bc44dfa06…7db5101a54

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (13)

BPS_DENOMINATOR()uint256
DEAD()address
WETH()address
authorizedCollectors(address)bool
authorizedRecipientManagers(address)bool
creatorBps()uint256
creatorMarketingWallet(address)address
creatorRecipientLocked(address)bool
owner()address
platformBps()uint256
platformRecipient()address
tokenCreatorRecipient(address)address
tokenCreatorRecipientLocked(address)bool

Events (8)

CollectorAuthorizationUpdatedCreatorMarketingWalletUpdatedFeeProcessedFeeSplitUpdatedOwnershipTransferredPlatformRecipientUpdatedRecipientManagerAuthorizationUpdatedTokenCreatorRecipientUpdated

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "platformRecipient_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "collector",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "authorized",
        "type": "bool"
      }
    ],
    "name": "CollectorAuthorizationUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "marketingWallet",
        "type": "address"
      }
    ],
    "name": "CreatorMarketingWalletUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "platformRecipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "creatorRecipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "platformEthAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "creatorEthAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "burnedTokenAmount",
        "type": "uint256"
      }
    ],
    "name": "FeeProcessed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "previousPlatformBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "previousCreatorBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newPlatformBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newCreatorBps",
        "type": "uint256"
      }
    ],
    "name": "FeeSplitUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousRecipient",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newRecipient",
        "type": "address"
      }
    ],
    "name": "PlatformRecipientUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "manager",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "authorized",
        "type": "bool"
      }
    ],
    "name": "RecipientManagerAuthorizationUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "previousRecipient",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newRecipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "manager",
        "type": "address"
      }
    ],
    "name": "TokenCreatorRecipientUpdated",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "BPS_DENOMINATOR",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "DEAD",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WETH",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "authorizedCollectors",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "authorizedRecipientManagers",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "clearMarketingWallet",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "creatorBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "creatorMarketingWallet",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "creatorRecipientLocked",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "platformBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "platformRecipient",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "feeToken",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "launchToken",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "processFee",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "platformEthAmount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "creatorEthAmount",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "collector",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "authorized",
        "type": "bool"
      }
    ],
    "name": "setAuthorizedCollector",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "manager",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "authorized",
        "type": "bool"
      }
    ],
    "name": "setAuthorizedRecipientManager",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "newPlatformBps",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "newCreatorBps",
        "type": "uint256"
      }
    ],
    "name": "setFeeSplit",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "marketingWallet",
        "type": "address"
      }
    ],
    "name": "setMarketingWallet",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newPlatformRecipient",
        "type": "address"
      }
    ],
    "name": "setPlatformRecipient",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "creator",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "setTokenCreatorRecipientByManager",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "tokenCreatorRecipient",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "tokenCreatorRecipientLocked",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

interface IERC20FeeDistributor {
    function transfer(address to, uint256 amount) external returns (bool);
}

interface IWETHFeeDistributor {
    function withdraw(uint256 amount) external;
}

contract FeeDistributor {
    address public constant WETH = 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73;
    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;

    uint256 public constant BPS_DENOMINATOR = 10_000;
    uint256 public platformBps;
    uint256 public creatorBps;

    address public owner;
    address public platformRecipient;

    mapping(address => bool) public authorizedCollectors;
    mapping(address => bool) public authorizedRecipientManagers;
    mapping(address => address) public creatorMarketingWallet;
    mapping(address => bool) public creatorRecipientLocked;
    mapping(address => address) public tokenCreatorRecipient;
    mapping(address => bool) public tokenCreatorRecipientLocked;
    bool private locked;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event PlatformRecipientUpdated(address indexed previousRecipient, address indexed newRecipient);
    event FeeSplitUpdated(
        uint256 previousPlatformBps,
        uint256 previousCreatorBps,
        uint256 newPlatformBps,
        uint256 newCreatorBps
    );
    event CollectorAuthorizationUpdated(address indexed collector, bool authorized);
    event RecipientManagerAuthorizationUpdated(address indexed manager, bool authorized);
    event CreatorMarketingWalletUpdated(address indexed creator, address indexed marketingWallet);
    event TokenCreatorRecipientUpdated(
        address indexed token,
        address indexed creator,
        address previousRecipient,
        address indexed newRecipient,
        address manager
    );
    event FeeProcessed(
        address indexed token,
        address indexed creator,
        address indexed platformRecipient,
        address creatorRecipient,
        uint256 ethAmount,
        uint256 platformEthAmount,
        uint256 creatorEthAmount,
        uint256 burnedTokenAmount
    );

    modifier onlyOwner() {
        require(msg.sender == owner, "ONLY_OWNER");
        _;
    }

    modifier onlyAuthorizedCollector() {
        require(authorizedCollectors[msg.sender], "ONLY_COLLECTOR");
        _;
    }

    modifier onlyAuthorizedRecipientManager() {
        require(authorizedRecipientManagers[msg.sender], "ONLY_RECIPIENT_MANAGER");
        _;
    }

    modifier nonReentrant() {
        require(!locked, "LOCKED");
        locked = true;
        _;
        locked = false;
    }

    constructor(address platformRecipient_) {
        require(platformRecipient_ != address(0), "ZERO_PLATFORM");
        owner = msg.sender;
        platformRecipient = platformRecipient_;
        platformBps = 3_000;
        creatorBps = 7_000;
        emit OwnershipTransferred(address(0), msg.sender);
        emit PlatformRecipientUpdated(address(0), platformRecipient_);
        emit FeeSplitUpdated(0, 0, platformBps, creatorBps);
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "ZERO_OWNER");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    function setPlatformRecipient(address newPlatformRecipient) external onlyOwner {
        require(newPlatformRecipient != address(0), "ZERO_PLATFORM");
        emit PlatformRecipientUpdated(platformRecipient, newPlatformRecipient);
        platformRecipient = newPlatformRecipient;
    }

    function setFeeSplit(uint256 newPlatformBps, uint256 newCreatorBps) external onlyOwner {
        require(newPlatformBps + newCreatorBps == BPS_DENOMINATOR, "BAD_BPS");
        emit FeeSplitUpdated(platformBps, creatorBps, newPlatformBps, newCreatorBps);
        platformBps = newPlatformBps;
        creatorBps = newCreatorBps;
    }

    function setAuthorizedCollector(address collector, bool authorized) external onlyOwner {
        require(collector != address(0), "ZERO_COLLECTOR");
        authorizedCollectors[collector] = authorized;
        emit CollectorAuthorizationUpdated(collector, authorized);
    }

    function setAuthorizedRecipientManager(address manager, bool authorized) external onlyOwner {
        require(manager != address(0), "ZERO_MANAGER");
        authorizedRecipientManagers[manager] = authorized;
        emit RecipientManagerAuthorizationUpdated(manager, authorized);
    }

    function setTokenCreatorRecipientByManager(address token, address creator, address recipient)
        external
        onlyAuthorizedRecipientManager
    {
        require(token != address(0), "ZERO_TOKEN");
        require(creator != address(0), "ZERO_CREATOR");
        require(recipient != address(0), "ZERO_RECIPIENT");
        address previousRecipient = tokenCreatorRecipient[token];
        tokenCreatorRecipient[token] = recipient;
        tokenCreatorRecipientLocked[token] = true;
        creatorRecipientLocked[creator] = true;
        emit TokenCreatorRecipientUpdated(token, creator, previousRecipient, recipient, msg.sender);
    }

    function setMarketingWallet(address marketingWallet) external {
        require(marketingWallet != address(0), "ZERO_MARKETING");
        require(!creatorRecipientLocked[msg.sender], "CREATOR_LOCKED");
        creatorMarketingWallet[msg.sender] = marketingWallet;
        emit CreatorMarketingWalletUpdated(msg.sender, marketingWallet);
    }

    function clearMarketingWallet() external {
        require(!creatorRecipientLocked[msg.sender], "CREATOR_LOCKED");
        creatorMarketingWallet[msg.sender] = address(0);
        emit CreatorMarketingWalletUpdated(msg.sender, address(0));
    }

    function processFee(address feeToken, address launchToken, address creator, uint256 amount)
        external
        onlyAuthorizedCollector
        nonReentrant
        returns (uint256 platformEthAmount, uint256 creatorEthAmount)
    {
        require(feeToken != address(0), "ZERO_FEE_TOKEN");
        require(launchToken != address(0), "ZERO_LAUNCH_TOKEN");
        require(launchToken != WETH, "BAD_LAUNCH_TOKEN");
        require(creator != address(0), "ZERO_CREATOR");

        if (amount == 0) {
            return (0, 0);
        }

        if (feeToken == WETH) {
            IWETHFeeDistributor(WETH).withdraw(amount);

            platformEthAmount = (amount * platformBps) / BPS_DENOMINATOR;
            creatorEthAmount = (amount * creatorBps) / BPS_DENOMINATOR;
            creatorEthAmount += amount - platformEthAmount - creatorEthAmount;

            address creatorRecipient = tokenCreatorRecipientLocked[launchToken]
                ? tokenCreatorRecipient[launchToken]
                : creatorMarketingWallet[creator];
            if (creatorRecipient == address(0)) {
                creatorRecipient = creator;
            }

            _sendETH(platformRecipient, platformEthAmount);
            _sendETH(creatorRecipient, creatorEthAmount);

            emit FeeProcessed(
                feeToken,
                creator,
                platformRecipient,
                creatorRecipient,
                amount,
                platformEthAmount,
                creatorEthAmount,
                0
            );
        } else {
            _safeTransfer(feeToken, DEAD, amount);
            emit FeeProcessed(feeToken, creator, platformRecipient, address(0), 0, 0, 0, amount);
        }
    }

    function _sendETH(address recipient, uint256 amount) internal {
        if (amount == 0) return;
        (bool ok, ) = payable(recipient).call{value: amount}("");
        require(ok, "ETH_TRANSFER_FAILED");
    }

    function _safeTransfer(address token, address to, uint256 value) internal {
        (bool ok, bytes memory data) = token.call(
            abi.encodeWithSelector(IERC20FeeDistributor.transfer.selector, to, value)
        );
        require(ok && (data.length == 0 || abi.decode(data, (bool))), "TOKEN_TRANSFER_FAILED");
    }

    receive() external payable {
        require(msg.sender == WETH, "ONLY_WETH");
    }
}
Chain explorer2599msChain node88ms