Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FeeRecipient
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.10; import "./interfaces/IFeeDispatcher.sol"; contract FeeRecipient { /// @notice Constructor replay prevention bool internal initialized; /// @notice Address where funds are sent to be dispatched IFeeDispatcher internal dispatcher; /// @notice Public Key root assigned to this receiver bytes32 internal publicKeyRoot; error AlreadyInitialized(); /// @notice Initializes the receiver /// @param _dispatcher Address that will handle the fee dispatching /// @param _publicKeyRoot Public Key root assigned to this receiver function init(address _dispatcher, bytes32 _publicKeyRoot) external { if (initialized) { revert AlreadyInitialized(); } initialized = true; dispatcher = IFeeDispatcher(_dispatcher); publicKeyRoot = _publicKeyRoot; } /// @notice Empty calldata fallback receive() external payable {} /// @notice Non-empty calldata fallback fallback() external payable {} /// @notice Triggers a withdrawal by sending its funds + its public key root to the dispatcher /// @dev Can be called by any wallet as recipients are not parameters function withdraw() external { dispatcher.dispatch{value: address(this).balance}(publicKeyRoot); } /// @notice Retrieve the assigned public key root function getPublicKeyRoot() external view returns (bytes32) { return publicKeyRoot; } /// @notice retrieve the assigned withdrawer function getWithdrawer() external view returns (address) { return dispatcher.getWithdrawer(publicKeyRoot); } }
//SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.10; import "./libs/DispatchersStorageLib.sol"; import "./interfaces/IStakingContractFeeDetails.sol"; import "./interfaces/IFeeDispatcher.sol"; /// @title Consensus Layer Fee Recipient /// @author Kiln /// @notice This contract can be used to receive fees from a validator and split them with a node operator contract ConsensusLayerFeeDispatcher is IFeeDispatcher { using DispatchersStorageLib for bytes32; event Withdrawal( address indexed withdrawer, address indexed feeRecipient, bytes32 pubKeyRoot, uint256 rewards, uint256 nodeOperatorFee, uint256 treasuryFee ); error TreasuryReceiveError(bytes errorData); error FeeRecipientReceiveError(bytes errorData); error WithdrawerReceiveError(bytes errorData); error ZeroBalanceWithdrawal(); error AlreadyInitialized(); error InvalidCall(); error NotImplemented(); bytes32 internal constant STAKING_CONTRACT_ADDRESS_SLOT = keccak256("ConsensusLayerFeeRecipient.stakingContractAddress"); uint256 internal constant BASIS_POINTS = 10_000; bytes32 internal constant VERSION_SLOT = keccak256("ConsensusLayerFeeRecipient.version"); /// @notice Ensures an initialisation call has been called only once per _version value /// @param _version The current initialisation value modifier init(uint256 _version) { if (_version != VERSION_SLOT.getUint256() + 1) { revert AlreadyInitialized(); } VERSION_SLOT.setUint256(_version); _; } /// @notice Constructor method allowing us to prevent calls to initCLFR by setting the appropriate version constructor(uint256 _version) { VERSION_SLOT.setUint256(_version); } /// @notice Initialize the contract by storing the staking contract /// @param _stakingContract Address of the Staking Contract function initCLD(address _stakingContract) external init(1) { STAKING_CONTRACT_ADDRESS_SLOT.setAddress(_stakingContract); } /// @notice Performs a withdrawal on this contract's balance function dispatch(bytes32) external payable { revert NotImplemented(); /* uint256 balance = address(this).balance; // this has taken into account msg.value if (balance == 0) { revert ZeroBalanceWithdrawal(); } IStakingContractFeeDetails stakingContract = IStakingContractFeeDetails( STAKING_CONTRACT_ADDRESS_SLOT.getAddress() ); address withdrawer = stakingContract.getWithdrawerFromPublicKeyRoot(_publicKeyRoot); address operator = stakingContract.getOperatorFeeRecipient(_publicKeyRoot); address treasury = stakingContract.getTreasury(); uint256 globalFee; if (balance >= 32 ether) { // withdrawing a healthy & exited validator globalFee = ((balance - 32 ether) * stakingContract.getGlobalFee()) / BASIS_POINTS; } else if (balance <= 16 ether) { // withdrawing from what looks like skimming globalFee = (balance * stakingContract.getGlobalFee()) / BASIS_POINTS; } uint256 operatorFee = (globalFee * stakingContract.getOperatorFee()) / BASIS_POINTS; (bool status, bytes memory data) = withdrawer.call{value: balance - globalFee}(""); if (status == false) { revert WithdrawerReceiveError(data); } if (globalFee > 0) { (status, data) = treasury.call{value: globalFee - operatorFee}(""); if (status == false) { revert FeeRecipientReceiveError(data); } } if (operatorFee > 0) { (status, data) = operator.call{value: operatorFee}(""); if (status == false) { revert TreasuryReceiveError(data); } } emit Withdrawal(withdrawer, operator, balance - globalFee, operatorFee, globalFee - operatorFee); */ } /// @notice Retrieve the staking contract address function getStakingContract() external view returns (address) { return STAKING_CONTRACT_ADDRESS_SLOT.getAddress(); } /// @notice Retrieve the assigned withdrawer for the given public key root /// @param _publicKeyRoot Public key root to get the owner function getWithdrawer(bytes32 _publicKeyRoot) external view returns (address) { IStakingContractFeeDetails stakingContract = IStakingContractFeeDetails( STAKING_CONTRACT_ADDRESS_SLOT.getAddress() ); return stakingContract.getWithdrawerFromPublicKeyRoot(_publicKeyRoot); } receive() external payable { revert InvalidCall(); } fallback() external payable { revert InvalidCall(); } }
//SPDX-License-Identifier: MIT pragma solidity >=0.8.10; library DispatchersStorageLib { function getUint256(bytes32 position) internal view returns (uint256 data) { assembly { data := sload(position) } } function setUint256(bytes32 position, uint256 data) internal { assembly { sstore(position, data) } } function getAddress(bytes32 position) internal view returns (address data) { assembly { data := sload(position) } } function setAddress(bytes32 position, address data) internal { assembly { sstore(position, data) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.10; interface IStakingContractFeeDetails { function getWithdrawerFromPublicKeyRoot(bytes32 _publicKeyRoot) external view returns (address); function getTreasury() external view returns (address); function getOperatorFeeRecipient(bytes32 pubKeyRoot) external view returns (address); function getGlobalFee() external view returns (uint256); function getOperatorFee() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.10; interface IFeeDispatcher { function dispatch(bytes32 _publicKeyRoot) external payable; function getWithdrawer(bytes32 _publicKeyRoot) external view returns (address); }
//SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.10; import "./libs/DispatchersStorageLib.sol"; import "./interfaces/IStakingContractFeeDetails.sol"; import "./interfaces/IFeeDispatcher.sol"; /// @title Execution Layer Fee Recipient /// @author Kiln /// @notice This contract can be used to receive fees from a validator and split them with a node operator contract ExecutionLayerFeeDispatcher is IFeeDispatcher { using DispatchersStorageLib for bytes32; event Withdrawal( address indexed withdrawer, address indexed feeRecipient, bytes32 pubKeyRoot, uint256 rewards, uint256 nodeOperatorFee, uint256 treasuryFee ); error TreasuryReceiveError(bytes errorData); error FeeRecipientReceiveError(bytes errorData); error WithdrawerReceiveError(bytes errorData); error ZeroBalanceWithdrawal(); error AlreadyInitialized(); error InvalidCall(); bytes32 internal constant STAKING_CONTRACT_ADDRESS_SLOT = keccak256("ExecutionLayerFeeRecipient.stakingContractAddress"); uint256 internal constant BASIS_POINTS = 10_000; bytes32 internal constant VERSION_SLOT = keccak256("ExecutionLayerFeeRecipient.version"); /// @notice Ensures an initialisation call has been called only once per _version value /// @param _version The current initialisation value modifier init(uint256 _version) { if (_version != VERSION_SLOT.getUint256() + 1) { revert AlreadyInitialized(); } VERSION_SLOT.setUint256(_version); _; } /// @notice Constructor method allowing us to prevent calls to initCLFR by setting the appropriate version constructor(uint256 _version) { VERSION_SLOT.setUint256(_version); } /// @notice Initialize the contract by storing the staking contract and the public key in storage /// @param _stakingContract Address of the Staking Contract function initELD(address _stakingContract) external init(1) { STAKING_CONTRACT_ADDRESS_SLOT.setAddress(_stakingContract); } /// @notice Performs a withdrawal on this contract's balance function dispatch(bytes32 _publicKeyRoot) external payable { uint256 balance = address(this).balance; if (balance == 0) { revert ZeroBalanceWithdrawal(); } IStakingContractFeeDetails stakingContract = IStakingContractFeeDetails( STAKING_CONTRACT_ADDRESS_SLOT.getAddress() ); address withdrawer = stakingContract.getWithdrawerFromPublicKeyRoot(_publicKeyRoot); address operator = stakingContract.getOperatorFeeRecipient(_publicKeyRoot); address treasury = stakingContract.getTreasury(); uint256 globalFee = (balance * stakingContract.getGlobalFee()) / BASIS_POINTS; uint256 operatorFee = (globalFee * stakingContract.getOperatorFee()) / BASIS_POINTS; (bool status, bytes memory data) = withdrawer.call{value: balance - globalFee}(""); if (status == false) { revert WithdrawerReceiveError(data); } if (globalFee > 0) { (status, data) = treasury.call{value: globalFee - operatorFee}(""); if (status == false) { revert FeeRecipientReceiveError(data); } } if (operatorFee > 0) { (status, data) = operator.call{value: operatorFee}(""); if (status == false) { revert TreasuryReceiveError(data); } } emit Withdrawal( withdrawer, operator, _publicKeyRoot, balance - globalFee, operatorFee, globalFee - operatorFee ); } /// @notice Retrieve the staking contract address function getStakingContract() external view returns (address) { return STAKING_CONTRACT_ADDRESS_SLOT.getAddress(); } /// @notice Retrieve the assigned withdrawer for the given public key root /// @param _publicKeyRoot Public key root to get the owner function getWithdrawer(bytes32 _publicKeyRoot) external view returns (address) { IStakingContractFeeDetails stakingContract = IStakingContractFeeDetails( STAKING_CONTRACT_ADDRESS_SLOT.getAddress() ); return stakingContract.getWithdrawerFromPublicKeyRoot(_publicKeyRoot); } receive() external payable { revert InvalidCall(); } fallback() external payable { revert InvalidCall(); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"getPublicKeyRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dispatcher","type":"address"},{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b506102a3806100206000396000f3fe6080604052600436106100405760003560e01c80632cc0b254146100495780633ccfd60b146100695780637d38d21f1461007e5780637f763702146100b057005b3661004757005b005b34801561005557600080fd5b5061004761006436600461021d565b6100ce565b34801561007557600080fd5b50610047610120565b34801561008a57600080fd5b5061009361018a565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100bc57600080fd5b506001546040519081526020016100a7565b60005460ff16156100f15760405162dc149f60e41b815260040160405180910390fd5b600080546001600160a01b03909316610100026001600160a81b03199093169290921760019081179092559055565b600054600154604051630ce1206560e41b815260048101919091526101009091046001600160a01b03169063ce1206509047906024016000604051808303818588803b15801561016f57600080fd5b505af1158015610183573d6000803e3d6000fd5b5050505050565b600080546001546040516313ef480b60e11b815260048101919091526101009091046001600160a01b0316906327de901690602401602060405180830381865afa1580156101dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102009190610249565b905090565b6001600160a01b038116811461021a57600080fd5b50565b6000806040838503121561023057600080fd5b823561023b81610205565b946020939093013593505050565b60006020828403121561025b57600080fd5b815161026681610205565b939250505056fea26469706673582212208eb3032a325d9c07889449598ba3999e3438d216376d0fb3031dbfbf383d522964736f6c634300080d0033
Deployed Bytecode
0x6080604052600436106100405760003560e01c80632cc0b254146100495780633ccfd60b146100695780637d38d21f1461007e5780637f763702146100b057005b3661004757005b005b34801561005557600080fd5b5061004761006436600461021d565b6100ce565b34801561007557600080fd5b50610047610120565b34801561008a57600080fd5b5061009361018a565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100bc57600080fd5b506001546040519081526020016100a7565b60005460ff16156100f15760405162dc149f60e41b815260040160405180910390fd5b600080546001600160a01b03909316610100026001600160a81b03199093169290921760019081179092559055565b600054600154604051630ce1206560e41b815260048101919091526101009091046001600160a01b03169063ce1206509047906024016000604051808303818588803b15801561016f57600080fd5b505af1158015610183573d6000803e3d6000fd5b5050505050565b600080546001546040516313ef480b60e11b815260048101919091526101009091046001600160a01b0316906327de901690602401602060405180830381865afa1580156101dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102009190610249565b905090565b6001600160a01b038116811461021a57600080fd5b50565b6000806040838503121561023057600080fd5b823561023b81610205565b946020939093013593505050565b60006020828403121561025b57600080fd5b815161026681610205565b939250505056fea26469706673582212208eb3032a325d9c07889449598ba3999e3438d216376d0fb3031dbfbf383d522964736f6c634300080d0033
Deployed Bytecode Sourcemap
106:1569:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;626:271;;;;;;;;;;-1:-1:-1;626:271:2;;;;;:::i;:::-;;:::i;1231:110::-;;;;;;;;;;;;;:::i;1553:120::-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;634:32:6;;;616:51;;604:2;589:18;1553:120:2;;;;;;;;1401:97;;;;;;;;;;-1:-1:-1;1478:13:2;;1401:97;;824:25:6;;;812:2;797:18;1401:97:2;678:177:6;626:271:2;708:11;;;;704:69;;;742:20;;-1:-1:-1;;;742:20:2;;;;;;;;;;;704:69;782:11;:18;;-1:-1:-1;;;;;810:40:2;;;782:18;810:40;-1:-1:-1;;;;;;810:40:2;;;;;;;796:4;810:40;;;;;;860:30;;626:271::o;1231:110::-;1270:10;;;1320:13;1270:64;;-1:-1:-1;;;1270:64:2;;;;;824:25:6;;;;1270:10:2;;;;-1:-1:-1;;;;;1270:10:2;;:19;;1297:21;;797:18:6;;1270:64:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1231:110::o;1553:120::-;1601:7;1627:10;;;1652:13;1627:39;;-1:-1:-1;;;1627:39:2;;;;;824:25:6;;;;1627:10:2;;;;-1:-1:-1;;;;;1627:10:2;;:24;;797:18:6;;1627:39:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1620:46;;1553:120;:::o;14:131:6:-;-1:-1:-1;;;;;89:31:6;;79:42;;69:70;;135:1;132;125:12;69:70;14:131;:::o;150:315::-;218:6;226;279:2;267:9;258:7;254:23;250:32;247:52;;;295:1;292;285:12;247:52;334:9;321:23;353:31;378:5;353:31;:::i;:::-;403:5;455:2;440:18;;;;427:32;;-1:-1:-1;;;150:315:6:o;860:251::-;930:6;983:2;971:9;962:7;958:23;954:32;951:52;;;999:1;996;989:12;951:52;1031:9;1025:16;1050:31;1075:5;1050:31;:::i;:::-;1100:5;860:251;-1:-1:-1;;;860:251:6:o
Swarm Source
ipfs://8eb3032a325d9c07889449598ba3999e3438d216376d0fb3031dbfbf383d5229
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.