Smart Contracts
/
SplitMain

SplitMain

0xSplits

SplitMain

A composable and gas-efficient protocol for deploying splitter contracts.

Split recipients, ownerships, and keeper fees are stored onchain as calldata & re-passed as args / validated via hashing when needed. Each split gets its own address & proxy for maximum composability with other contracts onchain. For these proxies, we extended EIP-1167 Minimal Proxy Contract to avoid DELEGATECALL inside receive() to accept hard gas-capped sends & transfers.

Methods

PERCENTAGE_SCALE

function PERCENTAGE_SCALE() external view returns (uint256)

constant to scale uints into percentages (1e6 == 100%)

Returns

NameTypeDescription
_0uint256undefined

acceptControl

function acceptControl(address split) external nonpayable

Accepts transfer of the controlling address of mutable split split

Parameters

NameTypeDescription
splitaddressAddress of mutable split to accept control transfer for

cancelControlTransfer

function cancelControlTransfer(address split) external nonpayable

Cancels transfer of the controlling address of mutable split split

Parameters

NameTypeDescription
splitaddressAddress of mutable split to cancel control transfer for

createSplit

function createSplit(address[] accounts, uint32[] percentAllocations, uint32 distributorFee, address controller) external nonpayable returns (address split)

Creates a new split with recipients accounts with ownerships percentAllocations, a keeper fee for splitting of distributorFee and the controlling address controller

💡

accounts must be ordered smallest to largest (i.e., 0x00, 0x01, 0x0a, 0x10, 0x1a, etc).

💡

for percentAllocations & distributorFee, 100% = PERCENTAGE_SCALE = 1e6

Parameters

NameTypeDescription
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution
controlleraddressControlling address (0x0 if immutable)

Returns

NameTypeDescription
splitaddressAddress of newly created split

distributeERC20

function distributeERC20(address split, contract ERC20 token, address[] accounts, uint32[] percentAllocations, uint32 distributorFee, address distributorAddress) external nonpayable

Distributes the ERC20 token balance for split split

accounts, percentAllocations, and distributorFee are verified by hashing & comparing to the hash in storage associated with split splitpernicious ERC20s may cause overflow in this function inside _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances

Parameters

NameTypeDescription
splitaddressAddress of split to distribute balance for
tokencontract ERC20Address of ERC20 to distribute balance for
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution
distributorAddressaddressAddress to pay distributorFee to

distributeETH

function distributeETH(address split, address[] accounts, uint32[] percentAllocations, uint32 distributorFee, address distributorAddress) external nonpayable

Distributes the ETH balance for split split

accounts, percentAllocations, and distributorFee are verified by hashing & comparing to the hash in storage associated with split split

Parameters

NameTypeDescription
splitaddressAddress of split to distribute balance for
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution
distributorAddressaddressAddress to pay distributorFee to

getController

function getController(address split) external view returns (address)

Returns the current controller of split split

Parameters

NameTypeDescription
splitaddressSplit to return controller for

Returns

NameTypeDescription
_0addressSplit's controller

getERC20Balance

function getERC20Balance(address account, contract ERC20 token) external view returns (uint256)

Returns the ERC20 balance of token token for account account

Parameters

NameTypeDescription
accountaddressAccount to return ERC20 token balance for
tokencontract ERC20Token to return balance for

Returns

NameTypeDescription
_0uint256Account's balance of token

getETHBalance

function getETHBalance(address account) external view returns (uint256)

Returns the current ETH balance of account account

Parameters

NameTypeDescription
accountaddressAccount to return ETH balance for

Returns

NameTypeDescription
_0uint256Account's balance of ETH

getHash

function getHash(address split) external view returns (bytes32)

Returns the current hash of split split

Parameters

NameTypeDescription
splitaddressSplit to return hash for

Returns

NameTypeDescription
_0bytes32Split's hash

getNewPotentialController

function getNewPotentialController(address split) external view returns (address)

Returns the current newPotentialController of split split

Parameters

NameTypeDescription
splitaddressSplit to return newPotentialController for

Returns

NameTypeDescription
_0addressSplit's newPotentialController

makeSplitImmutable

function makeSplitImmutable(address split) external nonpayable

Turns mutable split split immutable

Parameters

NameTypeDescription
splitaddressAddress of mutable split to turn immutable

predictImmutableSplitAddress

function predictImmutableSplitAddress(address[] accounts, uint32[] percentAllocations, uint32 distributorFee) external view returns (address split)

Predicts the address for an immutable split created with recipients accounts with ownerships percentAllocations and a keeper fee for splitting of distributorFee

Parameters

NameTypeDescription
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution

Returns

NameTypeDescription
splitaddressPredicted address of such an immutable split

transferControl

function transferControl(address split, address newController) external nonpayable

Begins transfer of the controlling address of mutable split split to newController

Two-step control transfer inspired by dharma

Parameters

NameTypeDescription
splitaddressAddress of mutable split to transfer control for
newControlleraddressAddress to begin transferring control to

updateAndDistributeERC20

function updateAndDistributeERC20(address split, contract ERC20 token, address[] accounts, uint32[] percentAllocations, uint32 distributorFee, address distributorAddress) external nonpayable

Updates & distributes the ERC20 token balance for split split

only callable by SplitControllerpernicious ERC20s may cause overflow in this function inside _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances

Parameters

NameTypeDescription
splitaddressAddress of split to distribute balance for
tokencontract ERC20Address of ERC20 to distribute balance for
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution
distributorAddressaddressAddress to pay distributorFee to

updateAndDistributeETH

function updateAndDistributeETH(address split, address[] accounts, uint32[] percentAllocations, uint32 distributorFee, address distributorAddress) external nonpayable

Updates & distributes the ETH balance for split split

only callable by SplitController

Parameters

NameTypeDescription
splitaddressAddress of split to distribute balance for
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution
distributorAddressaddressAddress to pay distributorFee to

updateSplit

function updateSplit(address split, address[] accounts, uint32[] percentAllocations, uint32 distributorFee) external nonpayable

Updates an existing split with recipients accounts with ownerships percentAllocations and a keeper fee for splitting of distributorFee

Parameters

NameTypeDescription
splitaddressAddress of mutable split to update
accountsaddress[]Ordered, unique list of addresses with ownership in the split
percentAllocationsuint32[]Percent allocations associated with each address
distributorFeeuint32Keeper fee paid by split to cover gas costs of distribution

walletImplementation

function walletImplementation() external view returns (address)

address of wallet implementation for split proxies

Returns

NameTypeDescription
_0addressundefined

withdraw

function withdraw(address account, uint256 withdrawETH, contract ERC20[] tokens) external nonpayable

Withdraw ETH &/ ERC20 balances for account account

Parameters

NameTypeDescription
accountaddressAddress to withdraw on behalf of
withdrawETHuint256Withdraw all ETH if nonzero
tokenscontract ERC20[]Addresses of ERC20s to withdraw

Events

CancelControlTransfer

event CancelControlTransfer(address indexed split)

emitted after each canceled split control transfer

Parameters

NameTypeDescription
split indexedaddressAddress of the split control transfer was canceled for

ControlTransfer

event ControlTransfer(address indexed split, address indexed previousController, address indexed newController)

emitted after each successful split control transfer

Parameters

NameTypeDescription
split indexedaddressAddress of the split control was transferred for
previousController indexedaddressAddress of the split's previous controller
newController indexedaddressAddress of the split's new controller

CreateSplit

event CreateSplit(address indexed split)

emitted after each successful split creation

Parameters

NameTypeDescription
split indexedaddressAddress of the created split

DistributeERC20

event DistributeERC20(address indexed split, contract ERC20 indexed token, uint256 amount, address indexed distributorAddress)

emitted after each successful ERC20 balance split

Parameters

NameTypeDescription
split indexedaddressAddress of the split that distributed its balance
token indexedcontract ERC20Address of ERC20 distributed
amountuint256Amount of ERC20 distributed
distributorAddress indexedaddressAddress to credit distributor fee to

DistributeETH

event DistributeETH(address indexed split, uint256 amount, address indexed distributorAddress)

emitted after each successful ETH balance split

Parameters

NameTypeDescription
split indexedaddressAddress of the split that distributed its balance
amountuint256Amount of ETH distributed
distributorAddress indexedaddressAddress to credit distributor fee to

InitiateControlTransfer

event InitiateControlTransfer(address indexed split, address indexed newPotentialController)

emitted after each initiated split control transfer

Parameters

NameTypeDescription
split indexedaddressAddress of the split control transfer was initiated for
newPotentialController indexedaddressAddress of the split's new potential controller

UpdateSplit

event UpdateSplit(address indexed split)

emitted after each successful split update

Parameters

NameTypeDescription
split indexedaddressAddress of the updated split

Withdrawal

event Withdrawal(address indexed account, uint256 ethAmount, contract ERC20[] tokens, uint256[] tokenAmounts)

emitted after each successful withdrawal

Parameters

NameTypeDescription
account indexedaddressAddress that funds were withdrawn to
ethAmountuint256Amount of ETH withdrawn
tokenscontract ERC20[]Addresses of ERC20s withdrawn
tokenAmountsuint256[]Amounts of corresponding ERC20s withdrawn

Errors

Create2Error

error Create2Error()

create2 opcode failed

CreateError

error CreateError()

create opcode failed

InvalidNewController

error InvalidNewController(address newController)

Invalid new controlling address newController for mutable split

Parameters

NameTypeDescription
newControlleraddressInvalid new controller

InvalidSplit__AccountsAndAllocationsMismatch

error InvalidSplit__AccountsAndAllocationsMismatch(uint256 accountsLength, uint256 allocationsLength)

Array lengths of accounts & percentAllocations don't match (accountsLength != allocationsLength)

Parameters

NameTypeDescription
accountsLengthuint256Length of accounts array
allocationsLengthuint256Length of percentAllocations array

InvalidSplit__AccountsOutOfOrder

error InvalidSplit__AccountsOutOfOrder(uint256 index)

Invalid accounts ordering at index

Parameters

NameTypeDescription
indexuint256Index of out-of-order account

InvalidSplit__AllocationMustBePositive

error InvalidSplit__AllocationMustBePositive(uint256 index)

Invalid percentAllocation of zero at index

Parameters

NameTypeDescription
indexuint256Index of zero percentAllocation

InvalidSplit__InvalidAllocationsSum

error InvalidSplit__InvalidAllocationsSum(uint32 allocationsSum)

Invalid percentAllocations sum allocationsSum must equal PERCENTAGE_SCALE

Parameters

NameTypeDescription
allocationsSumuint32Sum of percentAllocations array

InvalidSplit__InvalidDistributorFee

error InvalidSplit__InvalidDistributorFee(uint32 distributorFee)

Invalid distributorFee distributorFee cannot be greater than 10% (1e5)

Parameters

NameTypeDescription
distributorFeeuint32Invalid distributorFee amount

InvalidSplit__InvalidHash

error InvalidSplit__InvalidHash(bytes32 hash)

Invalid hash hash from split data (accounts, percentAllocations, distributorFee)

Parameters

NameTypeDescription
hashbytes32Invalid hash

InvalidSplit__TooFewAccounts

error InvalidSplit__TooFewAccounts(uint256 accountsLength)

Invalid number of accounts accountsLength, must have at least 2

Parameters

NameTypeDescription
accountsLengthuint256Length of accounts array

Unauthorized

error Unauthorized(address sender)

Unauthorized sender sender

Parameters

NameTypeDescription
senderaddressTransaction sender