Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 20 from a total of 20 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer | 24333193 | 37 hrs ago | IN | 0.01197372 ETH | 0.00000872 | ||||
| Transfer | 24317491 | 3 days ago | IN | 0.01254859 ETH | 0.00000315 | ||||
| Transfer | 24310636 | 4 days ago | IN | 0.01100468 ETH | 0.00000153 | ||||
| Transfer | 24303254 | 5 days ago | IN | 0.00966578 ETH | 0.00000197 | ||||
| Transfer | 24303091 | 5 days ago | IN | 0.01859092 ETH | 0.0000016 | ||||
| Transfer | 24297665 | 6 days ago | IN | 0.0090925 ETH | 0.00000382 | ||||
| Transfer | 24280235 | 8 days ago | IN | 0.0150166 ETH | 0.00000233 | ||||
| Transfer | 24269169 | 10 days ago | IN | 0.00989453 ETH | 0.0000018 | ||||
| Transfer | 24267228 | 10 days ago | IN | 0.01280296 ETH | 0.00000136 | ||||
| Transfer | 24264886 | 11 days ago | IN | 0.20492603 ETH | 0.0000026 | ||||
| Transfer | 24256345 | 12 days ago | IN | 0.00689284 ETH | 0.00000172 | ||||
| Transfer | 24255402 | 12 days ago | IN | 0.03514828 ETH | 0.00000349 | ||||
| Transfer | 24168072 | 24 days ago | IN | 0.00978968 ETH | 0.00000311 | ||||
| Transfer | 24129588 | 29 days ago | IN | 0.01188797 ETH | 0.0000031 | ||||
| Transfer | 24101406 | 33 days ago | IN | 0.0054444 ETH | 0.0000013 | ||||
| Transfer | 24079207 | 36 days ago | IN | 0.01767133 ETH | 0.00000127 | ||||
| Transfer | 24078029 | 37 days ago | IN | 0.00549248 ETH | 0.00000141 | ||||
| Transfer | 24049371 | 41 days ago | IN | 0.00611476 ETH | 0.00000116 | ||||
| Transfer | 24033257 | 43 days ago | IN | 0.0298561 ETH | 0.00001334 | ||||
| Transfer | 24016343 | 45 days ago | IN | 0.00753771 ETH | 0.00000182 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24333193 | 37 hrs ago | 0.00957898 ETH | ||||
| Transfer | 24333193 | 37 hrs ago | 0.00239474 ETH | ||||
| Transfer | 24317491 | 3 days ago | 0.01003887 ETH | ||||
| Transfer | 24317491 | 3 days ago | 0.00250971 ETH | ||||
| Transfer | 24310636 | 4 days ago | 0.00880374 ETH | ||||
| Transfer | 24310636 | 4 days ago | 0.00220093 ETH | ||||
| Transfer | 24303254 | 5 days ago | 0.00773262 ETH | ||||
| Transfer | 24303254 | 5 days ago | 0.00193315 ETH | ||||
| Transfer | 24303091 | 5 days ago | 0.01487274 ETH | ||||
| Transfer | 24303091 | 5 days ago | 0.00371818 ETH | ||||
| Transfer | 24297665 | 6 days ago | 0.007274 ETH | ||||
| Transfer | 24297665 | 6 days ago | 0.0018185 ETH | ||||
| Transfer | 24280235 | 8 days ago | 0.01201328 ETH | ||||
| Transfer | 24280235 | 8 days ago | 0.00300332 ETH | ||||
| Transfer | 24269169 | 10 days ago | 0.00791562 ETH | ||||
| Transfer | 24269169 | 10 days ago | 0.0019789 ETH | ||||
| Transfer | 24267228 | 10 days ago | 0.01024236 ETH | ||||
| Transfer | 24267228 | 10 days ago | 0.00256059 ETH | ||||
| Transfer | 24264886 | 11 days ago | 0.16394082 ETH | ||||
| Transfer | 24264886 | 11 days ago | 0.0409852 ETH | ||||
| Transfer | 24256345 | 12 days ago | 0.00551427 ETH | ||||
| Transfer | 24256345 | 12 days ago | 0.00137856 ETH | ||||
| Transfer | 24255402 | 12 days ago | 0.02811862 ETH | ||||
| Transfer | 24255402 | 12 days ago | 0.00702965 ETH | ||||
| Transfer | 24168072 | 24 days ago | 0.00978968 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Minimal Proxy Contract for 0x2f0bb99ffc519a37c3ba3d128e51b29a70c64e84
Contract Name:
Splitter
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 // SPDX-FileCopyrightText: 2024 Kiln <[email protected]> // // ██╗ ██╗██╗██╗ ███╗ ██╗ // ██║ ██╔╝██║██║ ████╗ ██║ // █████╔╝ ██║██║ ██╔██╗ ██║ // ██╔═██╗ ██║██║ ██║╚██╗██║ // ██║ ██╗██║███████╗██║ ╚████║ // ╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═══╝ // pragma solidity 0.8.22; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Operator} from "./Operator.sol"; /// @title Splitter /// @notice The Splitter contract is used to directly split any funds it receives between its owner and linked Operator contract Splitter { /// @notice The Operator contract that will receive a portion of the funds Operator public operator; /// @notice The owner of the contract address public owner; /// @notice The maximum value for a percentage in bps uint256 internal constant MAX_BPS = 10000; /// @notice Emitted when the contract is configured /// @param operator The Operator contract that will receive a portion of the funds /// @param owner The owner of the contract event Configured(address indexed operator, address indexed owner); /// @notice Emitted when the received funds are split /// @param operator The operator of the contract /// @param recipient The recipient of the funds /// @param operatorAmount The amount of funds that were sent to the operator /// @param recipientAmount The amount of funds that were sent to the recipient event Split(address indexed operator, address indexed recipient, uint256 operatorAmount, uint256 recipientAmount); /// @notice Emitted when the transfer to the owner fails and we explicitly do not revert /// @param errorData The error data returned by the transfer event OwnerTransferFailureCaught(bytes errorData); /// @notice Thrown when the contract is already initialized error AlreadyInitialized(); /// @notice Thrown when the sender is not the owner /// @param sender The sender of the transaction error Unauthorized(address sender); /// @notice Thrown when the transfer to the owner fails /// @param recipient The recipient of the transfer /// @param errorData The error data returned by the transfer error OwnerTransferFailed(address recipient, bytes errorData); /// @notice Thrown when the transfer to the operator fails /// @param errorData The error data returned by the transfer error OperatorTransferFailed(bytes errorData); /// @notice Thrown when the provided address is zero error InvalidZeroAddress(); /// @notice Thrown when the provided operator address is not a contract error InvalidOperatorAddress(); /// @notice Thrown when the initialization is performed more than once modifier uninitialized() { if (address(operator) != address(0) || address(owner) != address(0)) { revert AlreadyInitialized(); } _; } constructor() { operator = Operator(payable(address(uint160(uint256(bytes32("implem initialized")))))); } /// @notice The receive function is used to receive ETH receive() external payable { _split(owner, false); } /// @notice The fallback function is used to receive ETH when there is additional calldata fallback() external payable { _split(owner, false); } /// @notice Initializes the contract /// @param _operator The Operator contract that will receive a portion of the funds /// @param _owner The owner of the contract function init(Operator _operator, address _owner) external uninitialized { if (address(_operator) == address(0) || address(_owner) == address(0)) { revert InvalidZeroAddress(); } if (address(_operator).code.length == 0) { revert InvalidOperatorAddress(); } operator = _operator; owner = _owner; emit Configured(address(_operator), _owner); } /// @notice Claims the funds from the contract function claim() external { _split(owner, true); } /// @notice Claims the funds from the contract and sends them to the provided recipient /// @param recipient The recipient of the funds function claim(address recipient) external { if (msg.sender != owner) { revert Unauthorized(msg.sender); } _split(recipient, true); } /// @notice Claims the funds from the contract and sends them to the provided recipients /// @param recipient The recipient that receives the funds for the owner function _split(address recipient, bool revertOnTransferFail) internal { uint256 balance = address(this).balance; if (balance == 0) { return; } uint256 operatorFee = operator.operatorFee(); uint256 operatorAmount = operatorFee > 0 ? Math.mulDiv(balance, operatorFee, MAX_BPS) : 0; uint256 ownerAmount = balance - operatorAmount; (bool success, bytes memory rdata) = recipient.call{value: ownerAmount}(""); if (!success) { if (revertOnTransferFail) { revert OwnerTransferFailed(recipient, rdata); } else { emit OwnerTransferFailureCaught(rdata); return; } } (success, rdata) = address(operator).call{value: operatorAmount}(""); if (!success) { revert OperatorTransferFailed(rdata); } emit Split(address(operator), recipient, operatorAmount, ownerAmount); } }
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: BUSL-1.1 // SPDX-FileCopyrightText: 2024 Kiln <[email protected]> // // ██╗ ██╗██╗██╗ ███╗ ██╗ // ██║ ██╔╝██║██║ ████╗ ██║ // █████╔╝ ██║██║ ██╔██╗ ██║ // ██╔═██╗ ██║██║ ██║╚██╗██║ // ██║ ██╗██║███████╗██║ ╚████║ // ╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═══╝ // pragma solidity 0.8.22; import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; /// @title Operator /// @notice The Operator contract is used to store a commission distribution scheme for one or several Splitter instances /// @notice It stores a list of recipients alongside their respective percentages, and a fee that is taken on each Splitter /// @notice It then handles the dispatching of the commission between the configured recipient contract Operator is Ownable2Step { /// @notice The fee that is taken on each Splitter uint256 public operatorFee; /// @notice The maximum fee that can be configured on the Operator // solhint-disable-next-line immutable-vars-naming uint256 public immutable maximumOperatorFee; /// @notice The list of recipients address[] public recipients; /// @notice The list of percentages for each recipient uint256[] public percents; /// @notice The name of the operator string public name; /// @notice The maximum value for a percentage in bps uint256 internal constant MAX_BPS = 10000; /// @notice Emitted when the recipients are updated /// @param recipients The new list of recipients /// @param percentsBps The new list of percentages event UpdatedRecipients(address[] recipients, uint256[] percentsBps); /// @notice Emitted when the operator fee is updated /// @param operatorFee The new operator fee event UpdatedOperatorFee(uint256 operatorFee); /// @notice Emitted when the operator name is updated /// @param name The new operator name event UpdatedOperatorName(string name); /// @notice Emitted when the maximum operator fee is updated /// @param maximumOperatorFee The new maximum operator fee event UpdatedMaximumOperatorFee(uint256 maximumOperatorFee); /// @notice Emitted when the commission is claimed /// @param amount The amount that was claimed event Claimed(uint256 amount); /// @notice Thrown when the provided recipient list is empty error NoRecipients(); /// @notice Thrown when the provided recipient is null error ZeroAddress(); /// @notice Thrown when the provided percent value is zero error ZeroPercentBps(); /// @notice Thrown when the transfer to a recipient fails /// @param recipient The recipient that failed to receive the funds /// @param errorData The error data returned by the transfer error RecipientTransferFailed(address recipient, bytes errorData); /// @notice Thrown when the provided recipient list is empty error EmptyRecipientArguments(); /// @notice Thrown when the provided recipient list and percentage list have different lengths error InvalidArgumentLengths(); /// @notice Thrown when the provided percentages do not sum up to 10000 error InvalidPercentSum(); /// @notice Thrown when the provided fee is invalid /// @param feeBps The provided fee error InvalidFeeBps(uint256 feeBps); /// @notice Thrown when the provided name is empty error InvalidEmptyString(); /// @notice Thrown when the provided recipients are not sorted error InvalidUnsortedRecipients(); /// @param _owner The owner of the contract /// @param _operatorFee The fee that is taken on each Splitter /// @param _recipients The list of recipients, sorted in ascending order without duplicates /// @param _percents The list of percentages for each recipient constructor( address _owner, string memory _name, uint256 _operatorFee, uint256 _maximumOperatorFee, address[] memory _recipients, uint256[] memory _percents ) Ownable(_owner) { if (_maximumOperatorFee > MAX_BPS) { revert InvalidFeeBps(_maximumOperatorFee); } maximumOperatorFee = _maximumOperatorFee; emit UpdatedMaximumOperatorFee(_maximumOperatorFee); _setOperatorFee(_operatorFee); _setRecipients(_recipients, _percents); _setName(_name); } /// @notice The receive function is used to receive ETH receive() external payable { // do nothing } /// @notice The fallback function is used to receive ETH when there is additional calldata fallback() external payable { // do nothing } /// @notice Changes the operator fee /// @param _operatorFee The new operator fee function setOperatorFee(uint256 _operatorFee) external onlyOwner { _setOperatorFee(_operatorFee); } /// @notice Changes the recipients and their respective percentages /// @param _recipients The new list of recipients, sorted in ascending order without duplicates /// @param _percents The new list of percentages function setRecipients(address[] calldata _recipients, uint256[] calldata _percents) external onlyOwner { _setRecipients(_recipients, _percents); } /// @notice Changes the operator name /// @param _name The new operator name function setName(string calldata _name) external onlyOwner { _setName(_name); } /// @notice Claims the commission for all the recipients function claim() external { uint256 balance = address(this).balance; uint256 totalSent = 0; for (uint256 i = 0; i < recipients.length - 1;) { uint256 value = Math.mulDiv(balance, percents[i], MAX_BPS); (bool success, bytes memory rdata) = recipients[i].call{value: value}(""); if (!success) { revert RecipientTransferFailed(recipients[i], rdata); } totalSent += value; unchecked { ++i; } } { (bool success, bytes memory rdata) = recipients[recipients.length - 1].call{value: balance - totalSent}(""); if (!success) { revert RecipientTransferFailed(recipients[recipients.length - 1], rdata); } } emit Claimed(balance); } /// @notice Internal utility function to set the operator fee /// @param _operatorFee The new operator fee function _setOperatorFee(uint256 _operatorFee) internal { if (_operatorFee > maximumOperatorFee) { revert InvalidFeeBps(_operatorFee); } operatorFee = _operatorFee; emit UpdatedOperatorFee(_operatorFee); } /// @notice Internal utility function to set the recipients and their respective percentages /// @param _recipients The new list of recipients, sorted in ascending order without duplicates /// @param _percentsBps The new list of percentages function _setRecipients(address[] memory _recipients, uint256[] memory _percentsBps) internal { uint256 recipientsLength = _recipients.length; if (recipientsLength == 0) { revert EmptyRecipientArguments(); } if (recipientsLength != _percentsBps.length) { revert InvalidArgumentLengths(); } uint256 totalPercentsBps = 0; for (uint256 i = 0; i < recipientsLength; ++i) { totalPercentsBps += _percentsBps[i]; if (i > 0 && uint160(_recipients[i]) <= uint160(_recipients[i - 1])) { revert InvalidUnsortedRecipients(); } if (_recipients[i] == address(0)) { revert ZeroAddress(); } if (_percentsBps[i] == 0) { revert ZeroPercentBps(); } } if (totalPercentsBps != MAX_BPS) { revert InvalidPercentSum(); } recipients = _recipients; percents = _percentsBps; emit UpdatedRecipients(_recipients, _percentsBps); } /// @notice Internal utility function to set the operator name /// @param _name The new operator name function _setName(string memory _name) internal { if (bytes(_name).length == 0) { revert InvalidEmptyString(); } name = _name; emit UpdatedOperatorName(_name); } }
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"vulcan/=lib/vulcan/src/",
"deploy.sol/=lib/deploy.sol/src/",
"solmate/=lib/deploy.sol/lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidOperatorAddress","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[{"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"OperatorTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"OwnerTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Configured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"OwnerTransferFailureCaught","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"operatorAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipientAmount","type":"uint256"}],"name":"Split","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Operator","name":"_operator","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"contract Operator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.