# Splits — Full Documentation > Composable, open-source, audited smart contracts for managing onchain revenue. No protocol fees. Runs forever as a hyperstructure. This file contains the complete Splits documentation concatenated into a single document. For a curated index, see https://docs.splits.org/llms.txt --- # Docs Learn how Splits is used to manage onchain revenue Splits is a set of composable, [open-source](https://etherscan.io/address/0x2ed6c4b5da6378c7897ac67ba9e43102feb694ee#code), and [audited](https://github.com/0xSplits/splits-contracts/blob/main/audit/0xSplits_A-1.pdf) smart contracts that make it easy to manage onchain revenue. Running exactly at gas and charging no protocol fees, it takes the form of a [hyperstructure](https://jacob.energy/hyperstructures.html) that will run for free, forever, without any maintenance or trusted third parties. ![Onchain payment splits](./img/index_flow.png) These docs are designed for technical users. If you're non-technical, new to Ethereum, or just want to understand how you can use Splits today, we recommend you check out our [help center](https://splits.org/help/). ## Features - Free: No protocol fees – runs exactly at gas cost - Unstoppable: Non-upgradable contracts run as long as the underlying network exists - Multichain: Deployed on Ethereum, Optimism, Base, Zora, Polygon, Arbitrum + more - Open source: All contracts are [verified](https://etherscan.io/address/0x2ed6c4b5da6378c7897ac67ba9e43102feb694ee#code), [audited](https://github.com/0xSplits/splits-contracts/blob/main/audit/0xSplits_A-1.pdf), and publicly available on [Github](https://github.com/0xSplits) - Composable: Each contract has a payable address to receive ETH and ERC20 tokens - Efficient: Batched operations maximize gas efficiency at every step - Onchain: No third party APIs or external dependencies - Fair: Distribution costs are shared so small recipients aren't screwed - Automated: Bots and third parties may be incentivized to perform the repetitive tasks ## Usage Teams, platforms, and projects of all sizes rely on Splits to manage or help their users manage their onchain revenue. - Platforms: Zora, fxhash, Sound, Art Blocks, SuperRare, Titles, Arpeggi, Bonfire, 1stDibs - Collectives: Protocol Guild, Metalabel, Songcamp, Heds - Musicians: Daniel Allan, Reo Cragun, Coop Records, LNRZ, Venice Music - DAOs: Nouns, Airswap, MOROS NET, Bankless, GCR - Studios: Transient Labs, Props, Quantum ## Values We hope that sharing our values publicly will help you understand why the system is designed the way it is. - **Do one thing and do it well**. Empowering creative teams with simple, clear, and modular tools is the best way to create enduring value in the ecosystem. - **Trust is hard to build and easy to lose**. Security of the system is the highest order bit, and the system is only as secure as the foundation upon which it is built. - **Growing the pie matters more than growing the slice**. Composability within the ecosystem is the lifeblood of growth since it's experimentation at the edges where the most compelling discoveries happen. - **Tools must be credibly neutral**. This means they're rule-based, verifiable & open source, easy to understand, simple, and hard—if not impossible—to change. - **There are no solutions, only tradeoffs**. Considerations are context-specific and because something works in one situation does not mean it works in all. --- # Flow of funds There are three steps by which funds flow through the system to end recipients. ![Flow of funds](./img/flow_steps.png) ## Receiving ETH and ERC20 tokens can be sent directly to any of the contracts simply by using the contract's address. You can paste this address into any third-party platform or contract, including exchanges and others with hard gas limits. Funds received by a contract will be stored as a balance until a distribution occurs. You can learn more technical details about sending funds to a contract [here](/core). ## Distributing When a distribution occurs, funds sitting in the contract's balance will be allocated to each recipient's account in the protocol according to the rules of the contract. For example, when a Split is distributed the funds are allocated according to pre-defined percentages, whereas when a Waterfall is distributed funds are allocated sequentially according to the payout schedule. Instructions for distributing balances using the app are found in the help center, however, most people won't need to worry about this step since any contract with a bounty will eventually be distributed automatically by a bot or arbitrageur. The distribution step exists to maximize **composability and reliability**. The alternative, where funds are "pushed" to end recipients immediately upon being received by the contract, is expensive, unreliable, and insecure. Industry best practices recommend following a pull model, particularly when it comes to payments.[^1] [^2] This added step is mitigated by adding a bounty on the contract to incentivize third parties to execute distributions automatically. ## Withdrawing Once a contract's balance has been distributed, funds are ready to be withdrawn to any of the recipients' wallets. Since funds pile up in one place, withdrawing transfers _all the funds_ across _all the contracts_ for a given recipient. This saves people from having to initiate separate withdrawals for each contract they earn from. Since anyone can withdraw on behalf of any recipient ([instructions](https://splits.org/help/withdraw-balances/) ), recipients can be any account, smart contract, or exchange address. In addition to being more secure (discussed above), this step maximizes **gas efficiency** for recipients. By putting all the funds in one place, in a single transaction you're able to withdraw all your funds across all the contract you earn from. The alternative, where funds are sent to each recipient during a distribution, would use significantly more gas per distribution and limit the number of recipients a contract can have. With this pull-based withdraw step, the longer you wait to withdraw your funds, the more funds pile up, and the more gas you save. [^1]: [Smart contract best practices](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls) [^2]: [Pull over push](https://fravoll.github.io/solidity-patterns/pull_over_push.html) --- # Splits Development Kit This page explains how to use the **Splits Development Kit (SDK)**. The SDK makes it easier to query Splits metadata or call [contract functions](/core). You can find the SDK source code on [Github](https://github.com/0xSplits/splits-sdk). Older versions of the SDK will become partially unusable following the [sunset of the hosted service](https://thegraph.com/blog/sunbeam-upgrade-window/). All users should upgrade to the latest version before June 12. For the core SDK any version >= 4.0.0, and for the React SDK any version >= 2.0.0 Please see the [migration guide](https://github.com/0xSplits/splits-sdk/releases/tag/%400xsplits%2Fsplits-sdk%404.0.0), and reach out via [email](mailto:support@splits.org) with any questions. To get started, install the package using `yarn` or `npm`. ```bash yarn add @0xsplits/splits-sdk ``` ```bash npm install @0xsplits/splits-sdk ``` If you are migrating to v4, please see the [release note](https://github.com/0xSplits/splits-sdk/releases/tag/%400xsplits%2Fsplits-sdk%404.0.0). ## Subgraph Data Following the [sunset](https://thegraph.com/blog/sunbeam-upgrade-window/) of the hosted service and the release of v4 SDK we recommend everyone to use our SDK to access any data from the subgraph. You can create an API key by signing up on our app, and accessing your [account settings](https://app.splits.org/settings). If you think the SDK does not meet your requirements please reach out to the team and we would be happy to help. --- # Warehouse Begin by importing `WarehouseClient` into your app. ```js const warehouseClient = new WarehouseClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any split recipient or controller (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` ## Writes ### transfer Transfers the given amount of `tokenAddress` to `receiverAddress`. Usage ```js const args = { receiverAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342" tokenAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342" amount: 1 ether } const response = await warehouseClient.transfer(args) ``` Arguments ```graphql { receiverAddress: Address tokenAddress: Address amount: bigint } ``` Response ```graphql { event: Log # Transfer emitted on Warehouse } ``` ### transferFrom Transfers the given amount of `tokenAddress` from `senderAddress` to `receiverAddress`. Usage ```js const args = { senderAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", receiverAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", tokenAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", amount: 1 ether } const response = await warehouseClient.transferFrom(args) ``` Arguments ```graphql { senderAddress: Address receiverAddress: Address tokenAddress: Address amount: bigint } ``` Response ```graphql { event: Log # Transfer emitted on Warehouse } ``` ### approve Approves the given amount of `tokenAddress` to be spent by `spenderAddress`. Usage ```js const args = { spenderAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", tokenAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", amount: 1 ether } const response = await warehouseClient.approve(args) ``` Arguments ```graphql { spenderAddress: Address tokenAddress: Address amount: bigint } ``` Response ```graphql { event: Log # Approve emitted on Warehouse } ``` ### setOperator Sets `operatorAddress` as operator. Usage ```js const args = { operatorAddress: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', approved: true, } const response = await warehouseClient.setOperator(args) ``` Arguments ```graphql { operatorAddress: Address approved: boolean } ``` Response ```graphql { event: Log # OperatorSet emitted on Warehouse } ``` ### invalidateNonce Invalidates nonce for the caller. Usage ```js const args = { nonce: 0, } const response = await warehouseClient.invalidateNonce(args) ``` Arguments ```graphql { nonce: bigint } ``` Response ```graphql { event: Log # NonceInvalidated emitted on Warehouse } ``` ### temporaryApproveAndCall Grants temporary approval to `spenderAddress` for `tokenAddress` and makes a call to the given `targetAddress` with arbitrary passed data. Usage ```js const args = { spenderAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", operator: false, # if this is true, tokenAddress and amount should be 0. tokenAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", amount: 1 ether, targetAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", data: "0x0" } const response = await warehouseClient.temporaryApproveAndCall(args) ``` Arguments ```graphql { spenderAddress: Address operator: boolean tokenAddress: Address amount: bigint targetAddress: Address data: Hex } ``` Response ```graphql { txHash: Hex } ``` ### deposit Deposits a given amount of `tokenAddress` to the warehouse for the caller giving ownership of the receipt to `receiverAddress`. Usage ```js const args = { receiverAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" amount: 1 ether } const response = await warehouseClient.deposit(args) ``` Arguments ```graphql { receiverAddress: Address tokenAddress: Address amount: bigint } ``` Response ```graphql { event: Log # Transfer emitted on Warehouse } ``` ### batchDeposit Batch deposits given amounts of `tokenAddress` to the warehouse for the caller giving ownership of the receipt to `receiverAddresses`. Usage ```js const args = { receiversAddresses: ["0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9"] tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" amounts: [1 ether] } const response = await warehouseClient.batchDeposit(args) ``` Arguments ```graphql { receiversAddresses: Address tokenAddress: Address amounts: bigint[] } ``` Response ```graphql { events: Log[] # Transfer events emitted on Warehouse } ``` ### withdraw Withdraws the entire balance of `ownerAddress` for a given `tokenAddress`. This ignores the withdraw incentive present for the `ownerAddress`. If you are looking for an incentive on withdraw please use [this](#batchwithdraw). Usage ```js const args = { ownerAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" } const response = await warehouseClient.withdraw(args) ``` Arguments ```graphql { ownerAddress: Address tokenAddress: Address } ``` Response ```graphql { event: Log # Withdraw emitted on Warehouse } ``` ### batchWithdraw Withdraws a given amount of each `tokenAddress` for the `ownerAddress`. Also sends the withdraw incentive to the `withdrawerAddress`. Usage ```js const args = { ownerAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" tokensAddresses: ["0x64d91f12ece7362f91a6f8e7940cd55f05060b92"] amounts: [1 ether] withdrawerAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" } const response = await warehouseClient.batchWithdraw(args) ``` Arguments ```graphql { ownerAddress: Address tokensAddresses: Address[] amounts: bigint[] withdrawerAddress: Address } ``` Response ```graphql { events: Log[] # Withdraw events emitted on Warehouse } ``` ### batchTransfer Transfers given amounts of `tokenAddress` from the caller to the `receiversAddresses`. Usage ```js const args = { receiversAddresses: ["0x64d91f12ece7362f91a6f8e7940cd55f05060b92"] amounts: [1 ether] tokenAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" } const response = await warehouseClient.batchTransfer(args) ``` Arguments ```graphql { receiversAddresses: Address[] amounts: bigint[] tokenAddress: Address } ``` Response ```graphql { events: Log[] # Transfer events emitted on Warehouse } ``` ### setWithdrawConfig Sets the withdraw config on the warehouse for the caller. Usage ```js const args = { incentivePercent: 1 # max 6.5% paused: false } const response = await warehouseClient.setWithdrawConfig(args) ``` Arguments ```graphql { incentivePercent: number paused: boolean } ``` Response ```graphql { event: Log # withdrawConfigUpdated event emitted on Warehouse } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create split function would look like: ```js const args = { receiverAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" amount: 1 ether } const response = await warehouseClient.estimateGas.deposit(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create split function would look like: ```js const args = { receiverAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" amount: 1 ether } const response = await warehouseClient.calldata.deposit(args) ``` ## Reads ### getName Returns the name of the wrapped `tokenAddress`. Usage ```js const args = { tokenAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.getName(args) ``` Arguments ```graphql { tokenAddress: Address } ``` Response ```graphql { name: string } ``` ### getSymbol Returns the symbol of the wrapped `tokenAddress`. Usage ```js const args = { tokenAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.getSymbol(args) ``` Arguments ```graphql { tokenAddress: Address } ``` Response ```graphql { symbol: string } ``` ### getDecimals Returns the decimals of the wrapped `tokenAddress`. Usage ```js const args = { tokenAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.getDecimals(args) ``` Arguments ```graphql { tokenAddress: Address } ``` Response ```graphql { decimals: number } ``` ### getWithdrawConfig Returns the withdraw config set by the `userAddress`. Usage ```js const args = { userAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.getWithdrawConfig(args) ``` Arguments ```graphql { userAddress: Address } ``` Response ```graphql { incentive: number paused: boolean } ``` ### isValidNonce Returns the validity of the `userNonce` for the `userAddress`. Usage ```js const args = { userAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', userNonce: 0, } const response = await warehouseClient.isValidNonce(args) ``` Arguments ```graphql { userNonce: bigint userAddress: Address } ``` Response ```graphql { isValidNonce: boolean } ``` ### eip712Domain Returns EIP-712 domain of the warehouse. Usage ```js const response = await warehouseClient.eip712Domain() ``` Response ```graphql { chainId: number name: string salt: Hex verifyingContract: Address version: string } ``` ### isOperator Returns whether or not the `operatorAddress` is the operator for `ownerAddress`. Usage ```js const args = { ownerAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', operatorAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.isOperator(args) ``` Arguments ```graphql { ownerAddress: Address operatorAddress: Address } ``` Response ```graphql { isOperator: boolean } ``` ### balanceOf Returns the the amount of `tokenAddress` owned by `ownerAddress`. Usage ```js const args = { ownerAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', tokenAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.balanceOf(args) ``` Arguments ```graphql { ownerAddress: Address tokenAddress: Address } ``` Response ```graphql { balance: bigint } ``` ### allowance Returns the amount of allowance granted from `ownerAddress` to `spenderAddress` for a given `tokenAddress`. Usage ```js const args = { ownerAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', tokenAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', spenderAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await warehouseClient.allowance(args) ``` Arguments ```graphql { ownerAddress: Address tokenAddress: Address spenderAddress: Address } ``` Response ```graphql { allowance: bigint } ``` --- # Splits V2 Begin by importing `SplitV2Client` into your app. ```js const splitsClient = new SplitV2Client({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any split recipient or controller (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` ## Writes ### createSplit Creates a new Split contract. By default it creates a pull split. It also accepts a salt which can be used to deploy a split deterministically. Usage ```js const args = { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 50.0000 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 50.0000 } ], distributorFeePercent: 1.0000, totalAllocationPercent: 100.0000, splitType: SplitV2Type.Push, ownerAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", creatorAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", salt: "0x0000000000000000000000000000000000000000000000000000000000000000", chainId: 1 } const response = await splitsClient.createSplit(args) ``` Arguments ```graphql { recipients: { address: Address percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals totalAllocationPercent?: number splitType?: SplitV2Type # defaults to PullSplit ownerAddress?: Address # defaults to AddressZero for an immutable split creatorAddress?: Address # defaults to AddressZero salt?: bytes32 string # when not paused a non deterministic split will be deployed chainId?: number } ``` Response ```graphql { splitAddress: Address event: Log # SplitCreated emitted on PullSplitFactory and PushSplitFactory } ``` ### updateSplit Updates an existing mutable Split contract. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: "0x047ED5b8E8a7eDBd92FAF61f3117cAFE8c529ABb" recipients: { { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f"; percentAllocation: 50.0000 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675"; percentAllocation: 50.0000 }, } distributorFeePercent: 1.0000 totalAllocationPercent: 100.0000 } const response = await splitsClient.updateSplit(args) ``` ```graphql { recipients: { address: Address; percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals totalAllocationPercent?: number } ``` Response ```graphql { event: Log # SplitUpdated emitted on PushSplit and PullSplit } ``` ### distribute Distributes the balance of `tokenAddress` for `splitAddress`, and sends the distributor fee to `distributorAddress`. Usage ```js const args = { splitAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9", tokenAddress: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92", distributorAddress: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72" } const response = await splitsClient.distribute(args) ``` Arguments ```graphql { splitAddress: Address tokenAddress: Address distributorAddress?: Address } ``` Response ```graphql { event: Log # SplitDistributed emitted on PullSplit or PushSplit } ``` ### transferOwnership Transfers control of `splitAddress` to `newController`. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9", newOwner: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72" } const response = await splitsClient.initiateControlTransfer(args) ``` Arguments ```graphql { splitAddress: Address newOwner: Address } ``` Response ```graphql { event: Log # OwnershipTransferred emitted on PullSplit or PushSplit } ``` ### setPause Pauses distribution of the split. Can only be called by the controller of the split. Usage ```js const args = { splitAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9", paused: true } const response = await splitsClient.setPaused(args) ``` Arguments ```graphql { splitAddress: Address paused: boolean } ``` Response ```graphql { event: Log # SetPaused emitted on PullSplit or PushSplit } ``` ### execCalls Allows the controller of the split to execute arbitrary calls. Usage ```js const args = { splitAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9" calls: [{ to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", value: 1 ether, data: "0xd0e30db0" # deposit() }] } const response = await splitsClient.execCalls(args) ``` Arguments ```graphql { splitAddress: string calls: { to: Address, value: bigint, data: Hex }[] } ``` Response ```graphql { event: Log # ExecCalls emitted on PullSplit or PushSplit } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create split function would look like: ```js const args = { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 50.0000, }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 50.0000, } ], distributorFeePercent: 1.0000, ownerAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342" } const gasEstimate = await splitsClient.estimateGas.createSplit(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create split function would look like: ```js const args = { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f"; percentAllocation: 50.0000 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 50.0000, } ], distributorFeePercent: 1.0000, ownerAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342" } const callData = await splitsClient.callData.createSplit(args) ``` ## Reads ### getSplitBalance Returns the balance for a given `splitAddress` and `tokenAddress` in the split and the warehouse. Usage ```js const args = { splitAddress: '0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE', tokenAddress: '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', } const response = await splitsClient.getSplitBalance(args) ``` Arguments ```graphql { splitAddress: Address tokenAddress: Address } ``` Response ```graphql { splitBalance: bigint warehouseBalance: bigint } ``` ### predictDeterministicAddress Returns the deterministic address at which a Split will be deployed for given `recipients` and `distributorFeePercent`. Usage ```js const args = { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 50.0000 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 50.0000 } ], distributorFeePercent: 1.0000, totalAllocationPercent: 100.0000, splitType: SplitV2Type.Push, ownerAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", creatorAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", salt: "0x0000000000000000000000000000000000000000000000000000000000000000" } const response = await splitsClient.predictDeterministicAddress(args) ``` Arguments ```graphql { recipients: { address: Address; percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals totalAllocationPercent: number ownerAddress?: Address # defaults to AddressZero for an immutable split splitType?: SplitV2Type # defaults to PullSplit creatorAddress?: Address # defaults to AddressZero salt?: bytes32 string # when not paused a non deterministic split will be deployed } ``` Response ```graphql { splitAddress: Address } ``` ### isDeployed Returns the deterministic address at which a Split will be deployed for given `recipients` and `distributorFeePercent`. Also returns if the split is deployed. Usage ```js const args = { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 50.0000 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 50.0000 } ], distributorFeePercent: 1.0000, totalAllocationPercent: 100.0000, splitType: SplitV2Type.Push, ownerAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", creatorAddress: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", salt: "0x0000000000000000000000000000000000000000000000000000000000000000" } const response = await splitsClient.isDeployed(args) ``` Arguments ```graphql { recipients: { address: Address; percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals totalAllocationPercent: number ownerAddress?: Address # defaults to AddressZero for an immutable split splitType?: SplitV2Type # defaults to PullSplit creatorAddress?: Address # defaults to AddressZero salt?: bytes32 string # when not paused a non deterministic split will be deployed } ``` Response ```graphql { splitAddress: Address deployed: boolean } ``` ### owner Returns the owner for a given `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.owner(args) ``` Arguments ```graphql { splitAddress: Address } ``` Response ```graphql { ownerAddress: Address } ``` ### paused Returns the paused state for a given `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.paused(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { paused: boolean } ``` ### getReplaySafeHash Returns the wrapped hash for a given `splitAddress` and message or structured `hash`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', hash: '0x0', } const response = await splitsClient.getReplaySafeHash(args) ``` Arguments ```graphql { splitAddress: Address hash: Hex } ``` Response ```graphql { hash: Hex } ``` ### isValidSignature Given a message `hash` and a `signature`. It returns whether or not the `splitAddress` is the signer. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', hash: '0x0', signature: '0x0', } const response = await splitsClient.isValidSignature(args) ``` Arguments ```graphql { splitAddress: Address hash: Hex signature: Hex } ``` Response ```graphql { isValid: boolean } ``` ### getSplitMetadataViaProvider Returns all metadata for a given `splitAddress` by reading directly from the blockchain via RPC provider. This is useful for chains that are not yet indexed by the Splits subgraph. Works best with a provider that supports large log range searches (e.g. Alchemy). Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', chainId: 1, } const response = await splitsClient.getSplitMetadataViaProvider(args) ``` Arguments ```graphql { splitAddress: string chainId?: number } ``` Response ```graphql { split: Split # see the data client for the full Split type } ``` ### eip712Domain Returns EIP-712 domain of the `splitAddress` Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.eip712Domain(args) ``` Arguments ```graphql { splitAddress: Address } ``` Response ```graphql { chainId: number name: string salt: Hex verifyingContract: Address version: string } ``` --- # Splits V1 Begin by importing `SplitsClient` into your app. ```js const splitsClient = new SplitsClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any split recipient or controller (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }).splitV1 ``` ## SplitMain Writes ### createSplit Creates a new Split contract. Usage ```js const args = { recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, controller: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const response = await splitsClient.createSplit(args) ``` Arguments ```graphql { recipients: { address: string percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals controller?: string # defaults to AddressZero for an immutable split } ``` Response ```graphql { splitAddress: string event: Log # CreateSplit emitted on SplitMain } ``` ### updateSplit Updates an existing mutable Split contract. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: '0x047ED5b8E8a7eDBd92FAF61f3117cAFE8c529ABb', recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, } const response = await splitsClient.updateSplit(args) ``` Arguments ```graphql { splitAddress: string recipients: { address: string percentAllocation: number }[] distributorFeePercent: number } ``` Response ```graphql { event: Log # UpdateSplit emitted on SplitMain } ``` ### distributeToken Distributes the balance of `token` for `splitAddress`, and sends the distributor fee to `distributorAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', token: '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', distributorAddress: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await splitsClient.distributeToken(args) ``` Arguments ```graphql { splitAddress: string token: string distributorAddress?: string # defaults to signer } ``` Response ```graphql { event: Log # DistributeETH or DistributeERC20 emitted on SplitMain } ``` ### updateSplitAndDistributeToken This combines [updateSplit](#updatesplit) and [distributeToken](#distributetoken) into one transaction. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', token: '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, distributorAddress: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await splitsClient.updateSplitAndDistributeToken(args) ``` Arguments ```graphql { splitAddress: string token: string recipients: { address: string percentAllocation: number }[] distributorFeePercent: number distributorAddress?: string # defaults to signer } ``` Response ```graphql { event: Log # DistributeETH or DistributeERC20 emitted on SplitMain } ``` ### withdrawFunds Withdraws `tokens` for a given `address`. Usage ```js const args = { address: '0x357138F2690B82f29dF32bf2a3d0e6d4CC4D63C1', tokens: [ '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', '0x0000000000000000000000000000000000000000', ], } const response = await splitsClient.withdrawFunds(args) ``` Arguments ```graphql { address: string tokens: string[] } ``` Response ```graphql { event: Log # Withdrawal emitted on SplitMain } ``` ### initiateControlTransfer Transfers control of `splitAddress` to `newController`. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', newController: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await splitsClient.initiateControlTransfer(args) ``` Arguments ```graphql { splitAddress: string newController: string } ``` Response ```graphql { event: Log # InitiateControlTransfer emitted on SplitMain } ``` ### acceptControlTransfer Accepts control of `splitAddress`. Only callable by the new controller of `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.acceptControlTransfer(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { event: Log # ControlTransfer emitted on SplitMain } ``` ### cancelControlTransfer Cancels the transfer of `splitAddress`. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.cancelControlTransfer(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { event: Log # CancelControlTransfer emitted on SplitMain } ``` ### makeSplitImmutable Makes `splitAddress` immutable. Only callable by the controller of `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.makeSplitImmutable(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { event: Log # ControlTransfer emitted on SplitMain } ``` ### batchDistributeAndWithdraw Performs a multicall transaction, will distribute multiple tokens on a split and withdraw for any given addresses. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', tokens: [ '0x0000000000000000000000000000000000000000', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', ], recipientAddresses: [ '0x39883c6e81e273f381bffe5a8c26c3a866ff57ca', '0xeb78334dfde3afbc2b904f06153f59cc80ee07fa', '0x6b48ad78a26604b9e158a07ec4abb2981842e168', '0xc3313847E2c4A506893999f9d53d07cDa961a675', ], distributorAddress: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await splitsClient.batchDistributeAndWithdraw(args) ``` Arguments ```graphql { splitAddress: string tokens: string[] recipientAddresses: string[] distributorAddress?: string # defaults to signer } ``` Response ```graphql { events: Log[] } ``` ### batchDistributeAndWithdrawForAll Performs a multicall transaction, will distribute multiple tokens on a split and withdraw for all recipients. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', tokens: [ '0x0000000000000000000000000000000000000000', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', ], distributorAddress: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await splitsClient.batchDistributeAndWithdrawForAll(args) ``` Arguments ```graphql { splitAddress: string tokens: string[] distributorAddress?: string # defaults to signer } ``` Response ```graphql { events: Log[] } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create split function would look like: ```js const args = { recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, controller: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const gasEstimate = await splitsClient.estimateGas.createSplit(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create split function would look like: ```js const args = { recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, controller: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const callData = await splitsClient.callData.createSplit(args) ``` ## SplitMain Reads ### getSplitBalance Returns the balance for a given `splitAddress` and `token`. If no `token` is provided, returns the ETH balance. Usage ```js const args = { splitAddress: '0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE', token: '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', } const response = await splitsClient.getSplitBalance(args) ``` Arguments ```graphql { splitAddress: string token?: string # defaults to AddressZero } ``` Response ```graphql { balance: bigint } ``` ### predictImmutableSplitAddress Returns the determinisic address (using [CREATE2](https://eips.ethereum.org/EIPS/eip-1014)) at which an immutable Split will be deployed for given `recipients` and `distributorFeePercent`. Also returns whether or not this split has already been created. Usage ```js const args = { recipients: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, } const response = await splitsClient.predictImmutableSplitAddress(args) ``` Arguments ```graphql { recipients: { address: string percentAllocation: number }[] distributorFeePercent: number } ``` Response ```graphql { splitAddress: string splitExists: boolean } ``` ### getController Returns the controller for a given `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.getController(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { controller: string } ``` ### getNewPotentialController Returns the new potential controller (i.e., the account that needs to accept control) for a given `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.getNewPotentialController(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { newPotentialController: string } ``` ### getSplitMetadataViaProvider Returns all metadata for a given `splitAddress` by reading directly from the blockchain via RPC provider. This is useful for chains that are not yet indexed by the Splits subgraph. Works best with a provider that supports large log range searches (e.g. Alchemy). Not supported for V1 splits on Mainnet. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', chainId: 10, } const response = await splitsClient.getSplitMetadataViaProvider(args) ``` Arguments ```graphql { splitAddress: string chainId?: number } ``` Response ```graphql { split: Split # see the data client for the full Split type } ``` ### getHash Returns the current hash for a given `splitAddress`. Usage ```js const args = { splitAddress: '0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9', } const response = await splitsClient.getHash(args) ``` Arguments ```graphql { splitAddress: string } ``` Response ```graphql { hash: string } ``` --- # Splits Data Client The Splits Data client offers a comprehensive suite of functionalities for interfacing with the splits ecosystem. It provides detailed access to metadata related to various splits contracts, allowing for in-depth analysis and understanding of contract specifics. Additionally, the SDK enables connection to a GraphQL server that hosts a broad spectrum of data points and analyses, such as user earnings and contract earnings. This SDK is essential for developers looking to extract and leverage complex data within the splits ecosystem. Begin by importing `SplitsClient` into your app. ```js const dataClient = new SplitsClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any split recipient or controller (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }).dataClient ``` OR ```js import { DataClient } from '@0xsplits/splits-sdk' const dataClient = new DataClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, apiConfig, }) ``` ### getAccountMetadata Returns all metadata for a given `account`. Usage ```js const args = { chainId: 1, accountAddress: '0xF8843981e7846945960f53243cA2Fd42a579f719', } const response = await dataClient.getAccountMetadata(args) ``` Arguments ```graphql { chainId: number accountAddress: string } ``` Response [Split](#split) | [WaterfallModule](#waterfallmodule) | [LiquidSplit](#liquidsplit) | [Swapper](#swapper) | undefined ### getSplitMetadata Returns all metadata for a given `splitAddress`. Usage ```js const args = { chainId: 1, splitAddress: '0xF8843981e7846945960f53243cA2Fd42a579f719', } const response = await dataClient.getSplitMetadata(args) ``` Arguments ```graphql { chainId: number splitAddress: string } ``` Response [Split](#split) ### getLiquidSplitMetadata Returns all metadata for a given `liquidSplitAddress`. Usage ```js const args = { chainId: 1, liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', } const response = await dataClient.getLiquidSplitMetadata(args) ``` Arguments ```graphql { chainId: number liquidSplitAddress: string } ``` Response [Liquid Split](#liquidsplit) ### getVestingMetadata Returns all metadata for a given `vestingModuleAddress`. Usage ```js const args = { chainId: 1, vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', } const response = await dataClient.getVestingMetadata(args) ``` Arguments ```graphql { chainId: number vestingModuleAddress: string } ``` Response [Vesting Module](#vestingmodule) ### getWaterfallMetadata Returns all metadata for a given `waterfallModuleAddress`. Usage ```js const args = { chainId: 1, waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await dataClient.getWaterfallMetadata(args) ``` Arguments ```graphql { chainId: number waterfallModuleAddress: string } ``` Response [Waterfall Module](#waterfallmodule) ### getSwapperMetadata Returns all metadata for a given `swapperAddress`. Usage ```js const args = { chainId: 1, swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', } const response = await dataClient.getSwapperMetadata(args) ``` Arguments ```graphql { chainId: number swapperAddress: string } ``` Response [Swapper](#swapper) ### getRelatedSplits Returns all Splits related to a given `address`. Usage ```js const args = { chainId: 1, address: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const response = await dataClient.getRelatedSplits(args) ``` Arguments ```graphql { chainId: number address: string } ``` Response ```graphql { receivingFrom: Split[] controlling: Split[] pendingControl: Split[] } ``` Ref: [Split](#split) ### getContractEarnings Returns token balances for a given `contractAddress`. NOTE: Fetching active balances optionally takes an `erc20TokenList` argument. If the rpc url is not Alchemy or Infura, that token list is required. If the token list is passed in, balances will only be fetched for tokens in that list (as well as the native token and any previously distributed tokens). Otherwise, all erc20 transfers to the contract address will be reviewed with a `getLogs` request, but only Alchemy and Infura support a large enough `getLogs` request. You can disable fetching active balances by passing in `includeActiveBalances: false`. Usage ```js const args = { chainId: 1, contractAddress: '0xF8843981e7846945960f53243cA2Fd42a579f719', } const response = await dataClient.getContractEarnings(args) ``` Arguments ```graphql { chainId: number contractAddress: string includeActiveBalances?: boolean # defaults to true erc20TokenList?: string[] } ``` Response ```graphql { activeBalances?: { # tokens that are waiting to be distributed [token: string]: FormattedTokenBalances } distributed: { # tokens that have already been distributed [token: string]: FormattedTokenBalances } } ``` Ref: [FormattedTokenBalances](#formattedtokenbalances) ### getSplitEarnings Returns token balances for a given `splitAddress`. NOTE: Fetching active balances optionally takes an `erc20TokenList` argument. If the rpc url is not Alchemy or Infura, that token list is required. If the token list is passed in, balances will only be fetched for tokens in that list (as well as the native token and any previously distributed tokens). Otherwise, all erc20 transfers to the split address will be reviewed with a `getLogs` request, but only Alchemy and Infura support a large enough `getLogs` request. You can disable fetching active balances by passing in `includeActiveBalances: false`. Usage ```js const args = { chainId: 1, splitAddress: '0xF8843981e7846945960f53243cA2Fd42a579f719', } const response = await dataClient.getSplitEarnings(args) ``` Arguments ```graphql { chainId: number splitAddress: string includeActiveBalances?: boolean # defaults to true erc20TokenList?: string[] } ``` Response ```graphql { activeBalances?: { # tokens that are waiting to be distributed [token: string]: FormattedTokenBalances } distributed: { # tokens that have already been distributed [token: string]: FormattedTokenBalances } } ``` Ref: [FormattedTokenBalances](#formattedtokenbalances) ### getUserEarnings Returns token balances for a given `userAddress`. Usage ```js const args = { chainId: 1, userAddress: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const response = await dataClient.getUserEarnings(args) ``` Arguments ```graphql { chainId: number userAddress: string } ``` Response ```graphql { withdrawn: { # tokens the user has already withdrawn from the protocol [token: string]: FormattedTokenBalances } activeBalances: { # tokens that have been distributed but not yet withdrawn [token: string]: FormattedTokenBalances } } ``` Ref: [FormattedTokenBalances](#formattedtokenbalances) ### getUserEarningsByContract Returns token balances for a given `userAddress`, separated out by each Splits contract the user has received from. Can optionally pass in a list of `contractAddresses` to filter results to just a set of contracts. Usage ```js const args = { chainId: 1, userAddress: '0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342', } const response = await dataClient.getUserEarningsByContract(args) ``` Arguments ```graphql { chainId: number userAddress: string contractAddresses?: string[] } ``` Response ```graphql { withdrawn: { # tokens the user has already withdrawn from the protocol [token: string]: FormattedTokenBalances } activeBalances: { # tokens that have been distributed but not yet withdrawn [token: string]: FormattedTokenBalances } earningsByContract: { # Earnings broken out by each Splits contract the user has received from [contractAddress: string]: { balance: { [token: string]: FormattedTokenBalances } } } } ``` Ref: [FormattedTokenBalances](#formattedtokenbalances) ## Types ### Split ```graphql { type: 'Split' | 'SplitV2' address: string controller: { address: string ens?: string } | null newPotentialController: { address: string ens?: string } | null distributorFeePercent: number distributionsPaused: boolean distributeDirection: 'pull' | 'push' recipients: { percentAllocation: number recipient: { address: string ens?: string } }[] createdBlock: number } ``` ### Swapper ```graphql { type: 'Swapper' address: string beneficiary: { address: string ens?: string } tokenToBeneficiary: { address: string } owner: { address: string ens?: string } paused: boolean defaultScaledOfferFactorPercent: number scaledOfferFactorOverrides: { baseToken: { address: string } quoteToken: { address: string } scaledOfferFactorPercent: number }[] } ``` ### WaterfallModule ```graphql { type: 'WaterfallModule' address: string token: { address: string symbol?: string decimals?: number } nonWaterfallRecipient: { address: string ens?: string } | null tranches: { recipient: { address: string ens?: string } startAmount: number size?: number }[] } ``` ### LiquidSplit ```graphql { type: 'LiquidSplit' address: string distributorFeePercent: number payoutSplitAddress: string isFactoryGenerated: boolean holders: { percentAllocation: number recipient: { address: string ens?: string } }[] } ``` ### VestingModule ```graphql { type: 'VestingModule' address: string beneficiary: { address: string ens?: string } vestingPeriod: number streams?: { streamId: number startTime: number totalAmount: number releasedAmount: number token: { address: string symbol?: string decimals?: number } }[] } ``` ### FormattedTokenBalances ```graphql { symbol: string decimals: number rawAmount: bigint formattedAmount: string } ``` --- # Waterfall Begin by importing `WaterfallClient` into your app. If you are using the `SplitsClient`, you can access the waterfall client as well. ```js const waterfallClient = new WaterfallClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any waterfall recipient (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` OR ```js const splitsClient = new SplitsClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, }) const waterfallClient = splitsClient.waterfall ``` ## Waterfall Writes These functions make it easier to call [Waterfall functions](/core/waterfall). ### createWaterfallModule Creates a new Waterfall contract. Usage ```js const args = { token: "0x0000000000000000000000000000000000000000" tranches: [ { recipient: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", size: 5.2 # Receives the first 5.2 eth }, { recipient: "0xc3313847E2c4A506893999f9d53d07cDa961a675", size: 3 # Receives the next 3 eth }, { recipient: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", } ] } const response = await waterfallClient.createWaterfallModule(args) ``` Arguments ```graphql { token: string tranches: { recipient: string size?: number # the last tranche should have no size set, as it will receive all residual funds }[] nonWaterfallRecipient?: string # defaults to AddressZero, meaning any tranche recipient can recover non-waterfall tokens } ``` Response ```graphql { waterfallModuleAddress: string event: Log # CreateWaterfallModule emitted on WaterfallModuleFactory } ``` ### waterfallFunds Distributes the current balance for the given waterfall through it's tranches Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.waterfallFunds(args) ``` Arguments ```graphql { waterfallModuleAddress: string # If you have attempted to distribute the funds through the tranches, but are # hitting an error due to one of the tranche recipients being unable to receive # funds, you can call waterfallFunds with usePull set to true. This will set aside # the appropriate balance for each tranche recipient within the waterfall module # contract. Each recipient can then withdraw their funds using the withdrawPullFunds # function below. usePull?: boolean # defaults to false } ``` Response ```graphql { event: Log # WaterfallFunds emitted on the Waterfall contract } ``` ### recoverNonWaterfallFunds Recovers the balance of `token` for `waterfallModuleAddress` to the passed in recipient. Usage ```js const args = { waterfallModuleAddress: "0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC" token: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92" recipient: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72" } const response = await waterfallClient.recoverNonWaterfallFunds(args) ``` Arguments ```graphql { waterfallModuleAddress: string token: string # The recipient can be any of the tranche recipients on the waterfall. If a `nonWaterfallRecipient` # was set when the waterfall was created, then recipient must be that address recipient: string } ``` Response ```graphql { event: Log # RecoverNonWaterfallFunds on the Waterfall contract } ``` ### withdrawPullFunds Withdraws the funds for the passed in recipient that were set aside after a `waterfallFunds` call with `usePull` set to true. Usage ```js const args = { waterfallModuleAddress: "0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC" address: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72" } const response = await waterfallClient.withdrawPullFunds(args) ``` Arguments ```graphql { waterfallModuleAddress: string address: string } ``` Response ```graphql { event: Log # Withdrawal emitted on the Waterfall contract } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create waterfall module function would look like: ```js const args = { token: "0x0000000000000000000000000000000000000000" tranches: [ { recipient: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", size: 5.2 # Receives the first 5.2 eth }, { recipient: "0xc3313847E2c4A506893999f9d53d07cDa961a675", size: 3 # Receives the next 3 eth }, { recipient: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", } ] } const gasEstimate = await waterfallClient.estimateGas.createWaterfallModule(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create waterfall module function would look like: ```js const args = { token: "0x0000000000000000000000000000000000000000" tranches: [ { recipient: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", size: 5.2 # Receives the first 5.2 eth }, { recipient: "0xc3313847E2c4A506893999f9d53d07cDa961a675", size: 3 # Receives the next 3 eth }, { recipient: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", } ] } const callData = await waterfallClient.callData.createWaterfallModule(args) ``` ## Waterfall Reads These functions make it easier to query the [Waterfall contracts](/core/waterfall). ### getDistributedFunds Returns the distributed balance for a given `waterfallModuleAddress`. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.getDistributedFunds(args) ``` Arguments ```graphql { waterfallModuleAddress: string } ``` Response ```graphql { distributedFunds: bigint } ``` ### getFundsPendingWithdrawal Returns the pending balance for pull withdrawal for a given `waterfallModuleAddress`. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.getFundsPendingWithdrawal(args) ``` Arguments ```graphql { waterfallModuleAddress: string } ``` Response ```graphql { fundsPendingWithdrawal: bigint } ``` ### getTranches Returns the recipient list and threshold list for the tranches of a given `waterfallModuleAddress`. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.getTranches(args) ``` Arguments ```graphql { waterfallModuleAddress: string } ``` Response ```graphql { recipients: string[] thresholds: bigint[] } ``` ### getNonWaterfallRecipient Returns the non-waterfall recipient for a given `waterfallModuleAddress`. If none was set, returns the zero address. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.getNonWaterfallRecipient(args) ``` Arguments ```graphql { waterfallModuleAddress: string } ``` Response ```graphql { nonWaterfallRecipient: string } ``` ### getToken Returns the token for a given `waterfallModuleAddress`. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', } const response = await waterfallClient.getToken(args) ``` Arguments ```graphql { waterfallModuleAddress: string } ``` Response ```graphql { token: string } ``` ### getPullBalance Returns the balance set aside for withdrawal for a given `waterfallModuleAddress` and recipient address. Usage ```js const args = { waterfallModuleAddress: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', address: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await waterfallClient.getPullBalance(args) ``` Arguments ```graphql { waterfallModuleAddress: string address: string } ``` Response ```graphql { pullBalance: bigint } ``` --- # Swapper Begin by importing `SwapperClient` into your app. If you are using the `SplitsClient`, you can access the swapper client as well. ```js const swapperClient = new SwapperClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any swapper owner or beneficiary (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` OR ```js const splitsClient = new SplitsClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, }) const swapperClient = splitsClient.swapper ``` ## Swapper Writes These functions make it easier to call [Swapper functions](/core/swapper). ### createSwapper Creates a new Swapper contract. Usage ```js const args = { beneficiary: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', tokenToBeneficiary: '0x0000000000000000000000000000000000000000', defaultScaledOfferFactorPercent: 1, scaledOfferFactorOverrides: [ { baseToken: '0x0000000000000000000000000000000000000000', quoteToken: '0x0000000000000000000000000000000000000000', scaledOfferFactorPercent: 0.1, }, ], owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', oracleParams: { address: '0x8E0E20Ea43A88214A0908F32Cd14395022e823A6', }, } const response = await swapperClient.createSwapper(args) ``` Arguments ```graphql { beneficiary: string tokenToBeneficiary: string defaultScaledOfferFactorPercent: number scaledOfferFactorOverrides: { baseToken: string quoteToken: string scaledOfferFactorPercent: number }[] owner: string paused?: boolean # defaults to false oracleParams: { address?: string createOracleParams?: { factory: string data: string } } } ``` Response ```graphql { swapperAddress: string event: Log # CreateSwapper emitted on SwapperFactory } ``` ### universalSwap Swaps the given tokens for the Swapper's output token. Uses Splits' integration trader contract to trade with any router of your choice. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', inputAssets: [ { token: 0x0000000000000000000000000000000000000000, amountIn: BigInt('100000000000000000'), }, ], calls: [ { to: '0x123router', // router address value: BigInt('0'), data: '0x1234567890', // swap function data for the router } ] } const response = await swapperClient.universalSwap(args) ``` Arguments ```graphql { swapperAddress: string # swapper address inputAssets: { token: string # token address being swapped amountIn: bigint # amount of the token being swapped }[] # Calls to the router to swap the input assets for the output token, # you can use any router you want, generate the calls as you would for a smart account wallet. calls: { to: string # router address value: bigint # value to send to the router data: string # swap function data for the router }[] } ``` Response ```graphql { event: Log # Flash emitted on the Swapper contract } ``` ### uniV3FlashSwap Swaps the given tokens for the Swapper's output token. Uses Splits' integration trader contract to trade with UniswapV3. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', inputAssets: [ { encodedPath: '0xb4fbf271143f4fbf7b91a5ded31805e42b2208d60001f41f9840a85d5af5bf1d1762f925bdaddc4201f984', token: 0x0000000000000000000000000000000000000000, amountIn: BigInt('100000000000000000'), amountOutMin: BigInt('1000000000'), }, ], } const response = await swapperClient.uniV3FlashSwap(args) ``` Arguments ```graphql { swapperAddress: string # Will receive the excess funds from the uniswap trade after the swapper beneficiary gets their expected output excessRecipient?: string # defaults to signer # Inputs required for the exact input function for Uniswap V3 # See: https://docs.uniswap.org/contracts/v3/guides/swaps/multihop-swaps inputAssets: { encodedPath: string token: string amountIn: bigint amountOutMin: bigint }[] transactionTimeLimit?: number # In seconds } ``` Response ```graphql { event: Log # Flash emitted on the Swapper contract } ``` ### execCalls Execute the given list of calls from the Swapper. Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', calls: [ { to: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', value: BigInt(1), data: '0x0', }, ], } const response = await swapperClient.execCalls(args) ``` Arguments ```graphql { swapperAddress: string calls: { to: string value: bigint data: string }[] } ``` Response ```graphql { event: Log # ExecCalls on the Swapper contract } ``` ### setPaused Updates the pause state of the contract, which blocks executing swaps (except for the contract owner). Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', paused: true, } const response = await swapperClient.setPaused(args) ``` Arguments ```graphql { swapperAddress: string paused: boolean } ``` Response ```graphql { event: Log # SetPaused emitted on the Swapper contract } ``` ### setBeneficiary Updates the beneficiary of the swapper. Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', beneficiary: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await swapperClient.setBeneficiary(args) ``` Arguments ```graphql { swapperAddress: string beneficiary: string } ``` Response ```graphql { event: Log # SetBeneficiary emitted on the Swapper contract } ``` ### setTokenToBeneficiary Updates the token to the beneficiary of the swapper. Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', tokenToBeneficiary: '0x0000000000000000000000000000000000000000', } const response = await swapperClient.setTokenToBeneficiary(args) ``` Arguments ```graphql { swapperAddress: string tokenToBeneficiary: string } ``` Response ```graphql { event: Log # SetTokenToBeneficiary emitted on the Swapper contract } ``` ### setOracle Updates the oracle of the swapper. Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', oracle: '0x8E0E20Ea43A88214A0908F32Cd14395022e823A6', } const response = await swapperClient.setOracle(args) ``` Arguments ```graphql { swapperAddress: string oracle: string } ``` Response ```graphql { event: Log # SetOracle emitted on the Swapper contract } ``` ### setDefaultScaledOfferFactor Updates the default scaled offer factor of the swapper. Only callable by the Swapper owner. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', defaultScaledOfferFactorPercent: 1, } const response = await swapperClient.setDefaultScaledOfferFactor(args) ``` Arguments ```graphql { swapperAddress: string defaultScaledOfferFactorPercent: number } ``` Response ```graphql { event: Log # SetDefaultScaledOfferFactor emitted on the Swapper contract } ``` ### setScaledOfferFactorOverrides Updates the scaled offer factor overrides of the swapper. Only callable by the Swapper owner. NOTE: To remove an existing override you need to pass in a scaled offer factor percent of 100 which tells the contract to fallback to the default scaled offer factor. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', scaledOfferFactorOverrides: [ { baseToken: '0x0000000000000000000000000000000000000000', quoteToken: '0x0000000000000000000000000000000000000000', scaledOfferFactorPercent: 0.1, }, { baseToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', quoteToken: '0x0000000000000000000000000000000000000000', scaledOfferFactorPercent: 100, }, ], } const response = await swapperClient.setDefaultScaledOfferFactor(args) ``` Arguments ```graphql { swapperAddress: string scaledOfferFactorOverrides: { baseToken: string quoteToken: string scaledOfferFactorPercent: number }[] } ``` Response ```graphql { event: Log # SetPairScaledOfferFactors emitted on the Swapper contract } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create swapper function would look like: ```js const args = { beneficiary: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', tokenToBeneficiary: '0x0000000000000000000000000000000000000000', defaultScaledOfferFactorPercent: 1, scaledOfferFactorOverrides: [ { baseToken: '0x0000000000000000000000000000000000000000', quoteToken: '0x0000000000000000000000000000000000000000', scaledOfferFactorPercent: 0.1, }, ], owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', oracleParams: { address: '0x8E0E20Ea43A88214A0908F32Cd14395022e823A6', }, } const gasEstimate = await swapperClient.estimateGas.createSwapper(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create swapper function would look like: ```js const args = { beneficiary: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', tokenToBeneficiary: '0x0000000000000000000000000000000000000000', defaultScaledOfferFactorPercent: 1, scaledOfferFactorOverrides: [ { baseToken: '0x0000000000000000000000000000000000000000', quoteToken: '0x0000000000000000000000000000000000000000', scaledOfferFactorPercent: 0.1, }, ], owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', oracleParams: { address: '0x8E0E20Ea43A88214A0908F32Cd14395022e823A6', }, } const callData = await swapperClient.callData.createSwapper(args) ``` ## Swapper Reads These functions make it easier to query the [Swapper contracts](/core/swapper). ### getBeneficiary Returns the beneficiary for a given `swapperAddress`. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', } const response = await swapperClient.getBeneficiary(args) ``` Arguments ```graphql { swapperAddress: string } ``` Response ```graphql { beneficiary: string } ``` ### getTokenToBeneficiary Returns the token to beneficiary for a given `swapperAddress`. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', } const response = await swapperClient.getTokenToBeneficiary(args) ``` Arguments ```graphql { swapperAddress: string } ``` Response ```graphql { tokenToBeneficiary: string } ``` ### getOracle Returns the oracle for a given `swapperAddress`. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', } const response = await swapperClient.getOracle(args) ``` Arguments ```graphql { swapperAddress: string } ``` Response ```graphql { oracle: string } ``` ### getDefaultScaledOfferFactor Returns the default scaled offer factor for a given `swapperAddress`. Usage ```js const args = { swapperAddress: '0x693C49a6296d90e8A8936Ad4836a680F551bb97d', } const response = await swapperClient.getDefaultScaledOfferFactor(args) ``` Arguments ```graphql { swapperAddress: string } ``` Response ```graphql { defaultScaledOfferFactor: number } ``` --- # Liquid Splits Begin by importing `LiquidSplitClient` into your app. If you are using the `SplitsClient`, you can access the liquid split client as well. ```js const liquidSplitClient = new LiquidSplitClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any liquid split holder (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` OR ```js const splitsClient = new SplitsClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, }) const liquidSplitClient = splitsClient.liquidSplits ``` ## Liquid Split Writes These functions make it easier to call [Liquid Split functions](/templates/liquid). ### createLiquidSplit Creates a new Liquid Split contract. Usage ```js const args = { holders: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', } const response = await liquidSplitClient.createLiquidSplit(args) ``` Arguments ```graphql { holders: { address: string percentAllocation: number # >0 and <100 and up to 1 decimal }[] distributorFeePercent: number # <10 and up to 4 decimals owner?: string # defaults to signer } ``` Response ```graphql { liquidSplitAddress: string event: Log # CreateLS1155Clone emitted on LiquidSplitFactory } ``` ### distributeToken Distributes the current token balance for the given liquid split to the current NFT holders Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', token: '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', distributorAddress: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await liquidSplitClient.distributeToken(args) ``` Arguments ```graphql { liquidSplitAddress: string token: string distributorAddress?: string # defaults to signer } ``` Response ```graphql { event: Log # DistributeETH or DistributeERC20 emitted on the Liquid Split contract } ``` ### transferOwnership Transfer ownership of the given liquid split to the `newOwner`. Only callable by the owner of the liquid split contract. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', newOwner: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await liquidSplitClient.transferOwnership(args) ``` Arguments ```graphql { liquidSplitAddress: string newOwner: string } ``` Response ```graphql { event: Log # OwnershipTransferred emitted on the Liquid Split contract } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create liquid split function would look like: ```js const args = { holders: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', } const gasEstimate = await liquidSplitClient.estimateGas.createLiquidSplit(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create liquid split function would look like: ```js const args = { holders: [ { address: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', percentAllocation: 50.0, }, { address: '0xc3313847E2c4A506893999f9d53d07cDa961a675', percentAllocation: 50.0, }, ], distributorFeePercent: 1.0, owner: '0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f', } const callData = await liquidSplitClient.callData.createLiquidSplit(args) ``` ## Liquid Split Reads These functions make it easier to query the [Liquid Split contracts](/templates/liquid). ### getDistributorFee Returns the distributor fee of a given `liquidSplitAddress`. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', } const response = await liquidSplitClient.getDistributorFee(args) ``` Arguments ```graphql { liquidSplitAddress: string } ``` Response ```graphql { distributorFee: number } ``` ### getPayoutSplit Returns the payout split of a given `liquidSplitAddress`. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', } const response = await liquidSplitClient.getPayoutSplit(args) ``` Arguments ```graphql { liquidSplitAddress: string } ``` Response ```graphql { payoutSplitId: string } ``` ### getOwner Returns the owner of a given `liquidSplitAddress`. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', } const response = await liquidSplitClient.getOwner(args) ``` Arguments ```graphql { liquidSplitAddress: string } ``` Response ```graphql { owner: string } ``` ### getUri Returns the uri of a given `liquidSplitAddress`. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', } const response = await liquidSplitClient.getUri(args) ``` Arguments ```graphql { liquidSplitAddress: string } ``` Response ```graphql { uri: string } ``` ### getScaledPercentBalanceOf Returns the current percent ownership of a given `liquidSplitAddress` for an `address`. Usage ```js const args = { liquidSplitAddress: '0xb5Ce41320F3d486671918733BB3226E3981Db62b', address: '0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72', } const response = await liquidSplitClient.getScaledPercentBalanceOf(args) ``` Arguments ```graphql { liquidSplitAddress: string address: string } ``` Response ```graphql { scaledPercentBalance: number } ``` --- # Vesting Begin by importing `VestingClient` into your app. If you are using the `SplitsClient`, you can access the vesting client as well. ```js const vestingClient = new VestingClient({ chainId, publicClient, // viem public client (optional, required if using any of the contract functions) walletClient, // viem wallet client (optional, required if using any contract write functions. must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any vesting beneficiary (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. }) ``` OR ```js const splitsClient = new SplitsClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, }) const vestingClient = splitsClient.vesting ``` ## Vesting Writes These functions make it easier to call [Vesting functions](/core/vesting). ### createVestingModule Creates a new Vesting contract. Usage ```js const args = { beneficiary: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', vestingPeriodSeconds: 31536000, } const response = await vestingClient.createVestingModule(args) ``` Arguments ```graphql { beneficiary: string vestingPeriodSeconds: number } ``` Response ```graphql { vestingModuleAddress: string event: Log # CreateVestingModule emitted on VestingModuleFactory } ``` ### startVest Starts vesting streams for the given tokens. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', tokens: [ '0x0000000000000000000000000000000000000000', '0x64d91f12ece7362f91a6f8e7940cd55f05060b92', ], } const response = await vestingClient.startVest(args) ``` Arguments ```graphql { vestingModuleAddress: string tokens: string[] } ``` Response ```graphql { events: Log[] # CreateVestingStream emitted on the Vesting contract (one event per token) } ``` ### releaseVestedFunds Releases vested funds to the beneficiary for the given stream id's. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', streamIds: ['0', '1'], } const response = await vestingClient.releaseVestedFunds(args) ``` Arguments ```graphql { vestingModuleAddress: string streamIds: string[] } ``` Response ```graphql { events: Log[] # ReleaseFromVestingStream emitted on the Vesting contract (one event per stream) } ``` ## Gas Estimation The client has a gas estimation feature that can be used with any of the above write functions. Just call the function off of the `estimateGas` property. Estimating the gas for the create vesting module function would look like: ```js const args = { beneficiary: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', vestingPeriodSeconds: 31536000, } const gasEstimate = await vestingClient.estimateGas.createVestingModule(args) ``` ## CallData The client has a call data feature that can be used with any of the above write functions. Just call the function off of the `callData` property. Generating call data for the create vesting module function would look like: ```js const args = { beneficiary: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', vestingPeriodSeconds: 31536000, } const callData = await vestingClient.callData.createVestingModule(args) ``` ## Vesting Reads These functions make it easier to query the [Vesting contracts](/core/vesting). ### predictVestingModuleAddress Returns the vesting module address, and whether it exists yet, for the given beneficiary and vesting period. Usage ```js const args = { beneficiary: '0x8904D1fBfc9c88792aaaE8f452ac57E1Ba2130fC', vestingPeriodSeconds: 31536000, } const response = await vestingClient.predictVestingModuleAddress(args) ``` Arguments ```graphql { beneficiary: string vestingPeriodSeconds: number } ``` Response ```graphql { address: string exists: boolean } ``` ### getBeneficiary Returns the beneficiary for a given `vestingModuleAddress`. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', } const response = await vestingClient.getBeneficiary(args) ``` Arguments ```graphql { vestingModuleAddress: string } ``` Response ```graphql { beneficiary: string } ``` ### getVestingPeriod Returns the vesting period for a given `vestingModuleAddress`. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', } const response = await vestingClient.getVestingPeriod(args) ``` Arguments ```graphql { vestingModuleAddress: string } ``` Response ```graphql { vestingPeriod: bigint } ``` ### getVestedAmount Returns the vested amount for a given `vestingModuleAddress` and `streamId`. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', streamId: 0, } const response = await vestingClient.getVestedAmount(args) ``` Arguments ```graphql { vestingModuleAddress: string streamId: string } ``` Response ```graphql { amount: bigint } ``` ### getVestedAndUnreleasedAmount Returns the vested and unreleased amount for a given `vestingModuleAddress` and `streamId`. Usage ```js const args = { vestingModuleAddress: '0x0aab2E1E7D7bb0CAb1c0A49A59DCEfe241aA2ba1', streamId: 0, } const response = await vestingClient.getVestedAndUnreleasedAmount(args) ``` Arguments ```graphql { vestingModuleAddress: string streamId: string } ``` Response ```graphql { amount: bigint } ``` --- # Templates Begin by importing `TemplatesClient` into your app. If you are using the `SplitsClient`, you can access the templates client as well. ```js const templatesClient = new TemplatesClient({ chainId, publicClient, // viem public client walletClient, // viem wallet client }) ``` OR ```js const splitsClient = new SplitsClient({ chainId, publicClient, walletClient, includeEnsNames, ensPublicClient, }) const templatesClient = splitsClient.templates ``` Now you're ready to use any of the functions. All Arguments and Responses for these functions are `objects`. This will make it easier for us to release updates to the SDK without breaking existing implementations. ## Template Writes These functions make it easier to call various template contracts that combine Split core contracts together. ### createRecoup Calls a helper contract that creates a new Waterfall and potentially multiple Splits (a Waterfall tranche with multiple recipients will be a Split). A CreateRecoup event with the waterfall contract address is emitted by the helper contract and the Splits Subgraph will pick this up so that these Recoup Waterfalls can be displayed differently. Usage ```js const args = { token: "0x0000000000000000000000000000000000000000" tranches: [ { recipient: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", size: 5.2 # Receives the first 5.2 eth }, { recipient: "0xc3313847E2c4A506893999f9d53d07cDa961a675", size: 3 # Receives the next 3 eth }, { recipient: { recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 50 }, { address: "0xc3313847E2c4A506893999f9d53d07cDa961a675", percentAllocation: 30 }, { address: "0xEc8Bfc8637247cEe680444BA1E25fA5e151Ba342", percentAllocation: 20 } ], distributorFeePercent: 1 } } ] } const response = await templatesClient.createRecoup(args) ``` Arguments ```graphql { token: string tranches: { recipient: string | { recipients: { address: string percentAllocation: number # >0 and <100 and up to 4 decimals }[] distributorFeePercent: number # <10 and up to 4 decimals controller?: string # defaults to AddressZero for an immutable split } size?: number # the last tranche should have no size set, as it will receive all residual funds }[] nonWaterfallRecipientAddress?: string # defaults to AddressZero nonWaterfallRecipientTrancheIndex?: number # defaults to undefined } ``` Response ```graphql { waterfallModuleAddress: string event: Log # CreateRecoup emitted on Recoup } ``` #### Note on non-waterfall recipient If you want to set the non-waterfall recipient (i.e. the address that can receive any token that is not the waterfall token), you can use either nonWaterfallRecipientAddress or nonWaterfallRecipientTrancheIndex. If you have an address, set that. If you want to make a specific tranche the non-waterfall recipient, set the tranche index (remember that the first tranche is index 0). If you do not set either of them, the non-waterfall recipient will get set to the zero address, which means non-waterfall tokens can be recovered to any tranche recipient. #### Note on existing immutable splits If you are including an existing immutable split in the create recoup input, you must use just the Split's address and not the recipients/percent allocations for it. If you pass in the recipients the transaction will fail when it goes to create that immutable split since it already exists. ### createDiversifier Calls a helper contract that creates a new PassThroughWallet, a new Split, and potentially multiple Swappers. A CreateDiversifier event with the pass through wallet contract address is emitted by the helper contract and the Splits Subgraph will pick this up so that these Diversifiers can be displayed properly in the Splits app. Usage ```js const args = { owner: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f" oracleParams: { address: "0x8E0E20Ea43A88214A0908F32Cd14395022e823A6", }, recipients: [ { address: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", percentAllocation: 60 } { swapperParams: { beneficiary: "0x442C01498ED8205bFD9aaB6B8cc5C810Ed070C8f", tokenToBeneficiary: "0x0000000000000000000000000000000000000000", defaultScaledOfferFactorPercent: 1, scaledOfferFactorOverrides: [ { baseToken: "0x0000000000000000000000000000000000000000", quoteToken: "0x0000000000000000000000000000000000000000", scaledOfferFactorPercent: 0.1, } ], }, percentAllocation: 40 } ] } const response = await templatesClient.createDiversifier(args) ``` Arguments ```graphql { owner: string paused?: boolean # defaults to false oracleParams: { address?: string createOracleParams?: { factory: string data: string } } recipients: { address?: string swapperParams?: { beneficiary: string tokenToBeneficiary: string defaultScaledOfferFactorPercent: number scaledOfferFactorOverrides: { baseToken: string quoteToken: string scaledOfferFactorPercent: number }[] } percentAllocation: number }[] } ``` Response ```graphql { passThroughWalletAddress: string event: Log # CreateDiversifier emitted on DiversifierFactory } ``` --- # Multicall Batch transactions together into a single multicall transaction. This multicall function can be accessed through any of the sdk clients (Splits, Waterfall, Liquid Splits, Vesting). ### multicall Any write function from the SDK has a corresponding call data version that generates call data instead of submitting a transaction. That call data can be passed into a multicall transaction. Here is an example where a liquid split is a recipient of a split. First we distribute a token on the split, then we withdraw that token for the liquid split from SplitMain, then we distribute the liquid split. ``` const splitDistributionArgs = { splitAddress: "0xd9137B84f56D61Bb961082DD9Eb21bE3D7B14cB9", token: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92", distributorAddress: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72", } const splitDistributionCallData = await splitsClient.callData.distributeToken(splitDistributionArgs) const withdrawArgs = { address: "0xb5Ce41320F3d486671918733BB3226E3981Db62b", tokens: ["0x64d91f12ece7362f91a6f8e7940cd55f05060b92"], } const withdrawCallData = await splitsClient.callData.withdrawFunds(withdrawArgs) const liquidSplitDistributionArgs = { liquidSplitAddress: "0xb5Ce41320F3d486671918733BB3226E3981Db62b", token: "0x64d91f12ece7362f91a6f8e7940cd55f05060b92", distributorAddress: "0x2fa128274cfcf47afd4dc03cd3f2a59af09b6a72", } const liquidSplitDistributionCallData = await splitsClient.liquidSplits.callData.distributeToken(liquidSplitDistributionArgs) const response = await splitsClient.multicall({ calls: [splitDistributionCallData, withdrawCallData, liquidSplitDistributionCallData], }) ``` Arguments ```graphql { calls: CallData[] # call data objects can be generated by calling splitsClient.callData.functionName } ``` Response ```graphql { events: Log[] } ``` --- # Utilities The SDK exposes some of the utility functions and constants to make development with it easier. ### Constants All constants used in the SDK are available at `@0xsplits/splits-sdk/constants`. All ABI files used in the SDK are available at `@0xsplits/splits-sdk/constants/abi`. ### Errors All errors thrown from the SDK are available at `@0xsplits/splits-sdk/errors` ### Types All custom types defined and used in the SDK are available at `@0xsplits/splits-sdk/types` ### Utilities All validation functions used in the SDK are available at `@0xsplits/splits-sdk/utils/validation` --- # React SDK This page explains how to use the **React SDK**, a React wrapper around the [Core SDK](/sdk). The React SDK provides convenient hooks for easily fetching contract data and sending transactions. You can find the React SDK source code on [Github](https://github.com/0xSplits/splits-sdk/tree/main/packages/splits-sdk-react). To get started, install the package using `yarn` or `npm`. ```bash yarn add @0xsplits/splits-sdk-react ``` ```bash npm install @0xsplits/splits-sdk-react ``` ## Usage A `SplitsProvider` component is needed to manage context for all splits hooks. This sample code loads and displays a Split's basic metadata. ```js const SPLIT_ADDRESS = '0xF8843981e7846945960f53243cA2Fd42a579f719' const publicClient = createPublicClient({ chain: mainnet, transport: http() }) const splitsConfig = { chainId: 1, publicClient, } function App() { return ( ) } function YourComponents() { const { splitMetadata, isLoading } = useSplitMetadata(1, SPLIT_ADDRESS) if (isLoading) return Loading Split... if (!splitMetadata) return No Split found at address {SPLIT_ADDRESS} return ( Split: {splitMetadata.address} {splitMetadata.controller ? ( Controlled by: {splitMetadata.controller.address} ): ( No controller, Split is immutable )} Distribution incentive: {splitMetadata.distributorFeePercent}% Recipients {splitMetadata.recipients.map((recipient) => ( {recipient.recipient.address}: {recipient.percentAllocation}% ))} ) } ``` ## Initialization ### SplitsProvider Provider component that is needed to manage context for all splits hooks. It can optionally take in a splits config dictionary to initialize the SplitsClient. Usage ```js const splitsConfig = { chainId: 1, } function App() { return ( ) } function YourComponents() { return Hello World } ``` ### useSplitsClient Updates and returns the `SplitsClient` instance used by all hooks. Usage ```js const args = { chainId, publicClient, // viem public client walletClient, // viem wallet client (must have an account already attached) includeEnsNames, // boolean, defaults to false. If true, will return ens names for any recipient (only for mainnet) // If you want to return ens names on chains other than mainnet, you can pass in a mainnet public client // here. Be aware though that the ens name may not necessarily resolve to the proper address on the // other chain for non EOAs (e.g. Gnosis Safe's) ensPublicClient, // viem public client (optional) apiConfig: { apiKey: string // You can create an API key by signing up on our app, and accessing your account settings at app.splits.org/settings. }, // Splits GraphQL API key config, this is required for the data client to access the splits graphQL API. } const splitsClient = useSplitsClient(args) ``` ## Data Hooks ### useSplitEarnings Fetches the given split's earnings from the subgraph. Will also optionally fetch active balances. See [getSplitEarnings](/sdk/data#getsplitearnings) for more information on the input options. Usage ```js const { data: splitEarnings, isLoading, status, error } = useSplitEarnings( chainId, splitAddress, { includeActiveBalances, // defaults to true erc20TokenList, // defaults to undefined } ) ``` ### useUserEarnings Fetches the given user's earnings from the subgraph. Includes withdrawn amount and active balance (i.e. waiting to be withdrawn). See [getUserEarnings](/sdk/data#getuserearnings) for details on the metadata returned. Usage ```js const { data: userEarnings, isLoading, status, error } = useUserEarnings( chainId, userAddress, ) ``` ### useUserEarningsByContract Fetches the given user's earnings from the subgraph. Includes withdrawn amount and active balance (i.e. waiting to be withdrawn), as well as earnings broken down by each Splits contract the user receives from. Optionally takes a list of contractAddresses to filter down results to. See [getUserEarningsByContract](/sdk/data#getuserearningsbycontract) for details on the metadata returned. Usage ```js const { data: userEarningsByContract, isLoading, status, error } = useUserEarningsByContract( chainId, userAddress, { contractAddresses, // defaults to undefined, returning all contracts the user receives from } ) ``` ### useSplitMetadata Fetches the given split from the subgraph. See [getSplitMetadata](/sdk/data#getsplitmetadata) for details on the metadata returned. Usage ```js const { data: splitMetadata, isLoading, status, error } = useSplitMetadata(chainId, splitAddress) ``` ### useLiquidSplitMetadata Fetches the given liquid split from the subgraph. See [getLiquidSplitMetadata](/sdk/data#getliquidsplitmetadata) for details on the metadata returned. Usage ```js const { data: liquidSplitMetadata, isLoading, status, error } = useLiquidSplitMetadata(chainId, liquidsplitAddress) ``` ### useWaterfallMetadata Fetches the given waterfall module from the subgraph. See [getWaterfallMetadata](/sdk/data#getwaterfallmetadata) for details on the metadata returned. Usage ```js const { data: waterfallMetadata, isLoading, status, error } = useWaterfallMetadata(chainId, waterfallModuleAddress) ``` ### useVestingMetadata Fetches the given vesting module from the subgraph. See [getVestingMetadata](/sdk/data#getvestingmetadata) for details on the metadata returned. Usage ```js const { data: vestingMetadata, isLoading, status, error } = useVestingMetadata(chainId, vestingModuleAddress) ``` ### useSwapperMetadata Fetches the given swapper from the subgraph. See [getSwapperMetadata](/sdk/data#getswappermetadata) for details on the metadata returned. Usage ```js const { data: swapperMetadata, isLoading, status, error } = useSwapperMetadata(chainId, swapperAddress) ``` ## Warehouse Hooks Each of the transaction functions from the core sdk has a react hook wrapper. It returns the core sdk function and some state properties for monitoring the transaction progress. ### useWithdrawWarehouse See [withdraw](/sdk/warehouse#withdraw) for more details. Usage ```js const { withdrawWarehouse, status, txHash, error } = useWithdrawWarehouse() ``` Response ```graphql { withdrawWarehouse: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useBatchWithdrawWarehouse See [batch withdraw](/sdk/warehouse#batchwithdraw) for more details. Usage ```js const { batchWithdrawWarehouse, status, txHash, error } = useBatchWithdrawWarehouse() ``` Response ```graphql { batchWithdrawWarehouse: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Splits V2 Transaction Hooks Each of the transaction functions from the core sdk has a react hook wrapper. It returns the core sdk function and some state properties for monitoring the transaction progress. ### useCreateSplit See [createSplit](/sdk/splits-v2#createsplit) for more details. Usage ```js const { createSplit, status, txHash, error } = useCreateSplitV2() ``` Response ```graphql { createSplit: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useUpdateSplit See [updateSplit](/sdk/splits-v2#updatesplit) for more details. Usage ```js const { updateSplit, status, txHash, error } = useUpdateSplitV2() ``` Response ```graphql { updateSplit: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useDistributeToken See [distributeToken](/sdk/splits-v2#distribute) for more details. Usage ```js const { distributeToken, status, txHash, error } = useDistributeTokenV2() ``` Response ```graphql { distributeToken: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useTransferOwnership See [transferOwnership](/sdk/splits-v2#transferownership) for more details. Usage ```js const { transferOwnership, status, txHash, error } = useTransferOwnership() ``` Response ```graphql { transferOwnership: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSetPause See [setPause](/sdk/splits-v2#setpause) for more details. Usage ```js const { setPause, status, txHash, error } = useSetPause() ``` Response ```graphql { setPause: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useExecCalls See [execCalls](/sdk/splits-v2#execcalls) for more details. Usage ```js const { execCalls, status, txHash, error } = useExecCalls() ``` Response ```graphql { execCalls: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Splits V1 Transaction Hooks Each of the transaction functions from the core sdk has a react hook wrapper. It returns the core sdk function and some state properties for monitoring the transaction progress. ### useCreateSplit See [createSplit](/sdk/splits-v1#createsplit) for more details. Usage ```js const { createSplit, status, txHash, error } = useCreateSplit() ``` Response ```graphql { createSplit: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useUpdateSplit See [updateSplit](/sdk/splits-v1#updatesplit) for more details. Usage ```js const { updateSplit, status, txHash, error } = useUpdateSplit() ``` Response ```graphql { updateSplit: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useDistributeToken See [distributeToken](/sdk/splits-v1#distributetoken) for more details. Usage ```js const { distributeToken, status, txHash, error } = useDistributeToken() ``` Response ```graphql { distributeToken: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useUpdateSplitAndDistributeToken See [updateSplitAndDistributeToken](/sdk/splits-v1#updatesplitanddistributetoken) for more details. Usage ```js const { updateSplitAndDistributeToken, status, txHash, error } = useUpdateSplitAndDistributeToken() ``` Response ```graphql { updateSplitAndDistributeToken: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useWithdrawFunds See [withdrawFunds](/sdk/splits-v1#withdrawfunds) for more details. Usage ```js const { withdrawFunds, status, txHash, error } = useWithdrawFunds() ``` Response ```graphql { withdrawFunds: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useInitiateControlTransfer See [initiateControlTransfer](/sdk/splits-v1#initiatecontroltransfer) for more details. Usage ```js const { initiateControlTransfer, status, txHash, error } = useInitiateControlTransfer() ``` Response ```graphql { initiateControlTransfer: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useCancelControlTransfer See [cancelControlTransfer](/sdk/splits-v1#cancelcontroltransfer) for more details. Usage ```js const { cancelControlTransfer, status, txHash, error } = useCancelControlTransfer() ``` Response ```graphql { cancelControlTransfer: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useAcceptControlTransfer See [acceptControlTransfer](/sdk/splits-v1#acceptcontroltransfer) for more details. Usage ```js const { acceptControlTransfer, status, txHash, error } = useAcceptControlTransfer() ``` Response ```graphql { acceptControlTransfer: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useMakeSplitImmutable See [makeSplitImmutable](/sdk/splits-v1#makesplitimmutable) for more details. Usage ```js const { makeSplitImmutable, status, txHash, error } = useMakeSplitImmutable() ``` Response ```graphql { makeSplitImmutable: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Liquid Split Transaction Hooks ### useCreateLiquidSplit See [createLiquidSplit](/sdk/liquid#createliquidsplit) for more details. Usage ```js const { createLiquidSplit, status, txHash, error } = useCreateLiquidSplit() ``` Response ```graphql { createLiquidSplit: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useDistributeLiquidSplitToken See [distributeToken](/sdk/liquid#distributetoken) for more details. Usage ```js const { distributeToken, status, txHash, error } = useDistributeLiquidSplitToken() ``` Response ```graphql { distributeToken: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useTransferLiquidSplitOwnership See [transferOwnership](/sdk/liquid#transferownership) for more details. Usage ```js const { transferOwnership, status, txHash, error } = useTransferLiquidSplitOwnership() ``` Response ```graphql { transferOwnership: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Waterfall Transaction Hooks ### useCreateWaterfallModule See [createWaterfallModule](/sdk/waterfall#createwaterfallmodule) for more details. Usage ```js const { createWaterfallModule, status, txHash, error } = useCreateWaterfallModule() ``` Response ```graphql { createWaterfallModule: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useWaterfallFunds See [waterfallFunds](/sdk/waterfall#waterfallfunds) for more details. Usage ```js const { waterfallFunds, status, txHash, error } = useWaterfallFunds() ``` Response ```graphql { waterfallFunds: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useRecoverNonWaterfallFunds See [recoverNonWaterfallFunds](/sdk/waterfall#recovernonwaterfallfunds) for more details. Usage ```js const { recoverNonWaterfallFunds, status, txHash, error } = useRecoverNonWaterfallFunds() ``` Response ```graphql { recoverNonWaterfallFunds: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useWithdrawWaterfallPullFunds See [withdrawPullFunds](/sdk/waterfall#withdrawpullfunds) for more details. Usage ```js const { withdrawPullFunds, status, txHash, error } = useWithdrawWaterfallPullFunds() ``` Response ```graphql { withdrawPullFunds: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Vesting Transaction Hooks ### useCreateVestingModule See [createVestingModule](/sdk/vesting#createvestingmodule) for more details. Usage ```js const { createVestingModule, status, txHash, error } = useCreateVestingModule() ``` Response ```graphql { createVestingModule: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useStartVest See [startVest](/sdk/vesting#startvest) for more details. Usage ```js const { startVest, status, txHash, error } = useStartVest() ``` Response ```graphql { startVest: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useReleaseVestedFunds See [releaseVestedFunds](/sdk/vesting#releasevestedfunds) for more details. Usage ```js const { releaseVestedFunds, status, txHash, error } = useReleaseVestedFunds() ``` Response ```graphql { releaseVestedFunds: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Swapper Transaction Hooks ### useCreateSwapper See [createSwapper](/sdk/swapper#createswapper) for more details. Usage ```js const { createSwapper, status, txHash, error } = useCreateSwapper() ``` Response ```graphql { createSwapper: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useUniversalSwap See [universalSwap](/sdk/swapper#universalswap) for more details. Usage ```js const { universalSwap, status, txHash, error } = useUniversalSwap() ``` Response ```graphql { universalSwap: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useUniV3FlashSwap See [uniV3FlashSwap](/sdk/swapper#univ3flashswap) for more details. Usage ```js const { uniV3FlashSwap, status, txHash, error } = useUniV3FlashSwap() ``` Response ```graphql { uniV3FlashSwap: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperExecCalls See [execCalls](/sdk/swapper#execcalls) for more details. Usage ```js const { execCalls, status, txHash, error } = useSwapperExecCalls() ``` Response ```graphql { execCalls: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperPause See [setPaused](/sdk/swapper#setpaused) for more details. Usage ```js const { setPaused, status, txHash, error } = useSwapperPause() ``` Response ```graphql { setPaused: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperSetBeneficiary See [setBeneficiary](/sdk/swapper#setbeneficiary) for more details. Usage ```js const { setBeneficiary, status, txHash, error } = useSwapperSetBeneficiary() ``` Response ```graphql { setBeneficiary: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperSetTokenToBeneficiary See [setTokenToBeneficiary](/sdk/swapper#settokentobeneficiary) for more details. Usage ```js const { setTokenToBeneficiary, status, txHash, error } = useSwapperSetTokenToBeneficiary() ``` Response ```graphql { setTokenToBeneficiary: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperSetOracle See [setOracle](/sdk/swapper#setoracle) for more details. Usage ```js const { setOracle, status, txHash, error } = useSwapperSetOracle() ``` Response ```graphql { setOracle: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperSetDefaultScaledOfferFactor See [setDefaultScaledOfferFactor](/sdk/swapper#setdefaultscaledofferfactor) for more details. Usage ```js const { setDefaultScaledOfferFactor, status, txHash, error } = useSwapperSetDefaultScaledOfferFactor() ``` Response ```graphql { setDefaultScaledOfferFactor: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ### useSwapperSetScaledOfferFactorOverrides See [setScaledOfferFactorOverrides](/sdk/swapper#setscaledofferfactoroverrides) for more details. Usage ```js const { setScaledOfferFactorOverrides, status, txHash, error } = useSwapperSetScaledOfferFactorOverrides() ``` Response ```graphql { setScaledOfferFactorOverrides: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Template Transaction Hooks ### useCreateRecoup See [createRecoup](/sdk/templates#createrecoup) for more details. Usage ```js const { createRecoup, status, txHash, error } = useCreateRecoup() ``` Response ```graphql { createRecoup: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` ## Multicall Transaction Hooks ### useMulticall See [multicall](/sdk/multicall#multicall) for more details. Usage ```js const { multicall, status, txHash, error } = useMulticall() ``` Response ```graphql { multicall: function status?: 'pendingApproval' | 'txInProgress' | 'complete' | 'error' txHash?: string error?: any } ``` --- # SplitsKit This page explains how to use **SplitsKit**, a React component library around the [React SDK](/react). SplitsKit provides convenient hooks for easily fetching contract data and sending transactions. You can find the React SDK source code on [Github](https://github.com/0xSplits/splits-sdk/tree/main/packages/splits-kit). Get an interactive demo of the components by visiting [the Storybook](https://splits-kit.vercel.app/?path=/story/introduction--introduction). To get started, install the package using `yarn` or `npm`. ```bash yarn add @0xsplits/splits-kit ``` ```bash npm install @0xsplits/splits-kit ``` ## Usage Like the [React SDK](/react), a `SplitsProvider` component is needed to manage context for all components. SplitsKit also uses wagmi, so you will need to wrap your app in a `WagmiConfig` as well. This sample code loads and displays a DisplaySplit component. ```js import '@0xsplits/splits-kit/dist/styles.css' const SPLIT_ADDRESS = '0xF8843981e7846945960f53243cA2Fd42a579f719' const { publicClient, webSocketPublicClient } = configureChains( [mainnet], [publicProvider()], ) const splitsConfig = { chainId: 1, publicClient, } const wagmiConfig = createConfig({ publicClient, webSocketPublicClient, }) export default function App() { return ( ) } function YourComponents() { return ( ) } ``` ## Initialization ### SplitsProvider Provider component that is needed to manage context for all SplitsKit components. See documentation in the [React SDK](/react#splitsprovider). ### WagmiConfig Config component for Wagmi. See documentation in the [Wagmi docs](https://wagmi.sh/react/WagmiConfig). ## Components ### CreateSplit A form for creating a new split. Usage ```js {}} // called when the split is successfully created /> ``` ### DisplaySplit Display a split with its recipients and balances, with ability to distribute balances. } > In order to display/distribute balances, [SplitsProvider](/splits-kit#splitsprovider) must be passed an [Alchemy](https://wagmi.sh/react/providers/alchemy) or [Infura](https://wagmi.sh/react/providers/infura) `publicClient`. Usage ```js {}} // called when the split is successfully distributed onError={() => {}} // called when the split fails to distribute /> ``` --- # Core contracts This section describes the various smart contract building blocks upon which all payment flows are built. ## Flow of funds We recommend reading the [flow of funds](/flow) page if you haven't already. The below diagram shows the different methods for moving funds through the system. Though each contract's _distribution logic_ is unique, the general three steps are the same. ![Flow of funds](./core/img/flow_of_funds.png) 1. **Receive**: ETH and ERC20 tokens flow into the contract via `send`, `transfer`, or `call` and the contract's balance increases. 2. **Distribute**: Once a contract has a positive balance, anyone can call `distribute`, `distributeETH` or `distributeERC20` depending on the version of the split and earn the distributor fee. 3. **Withdraw**: Anyone can call `withdraw` at any time for any account, thereby pushing that account's balance out of SplitWarehouse or SplitMain to the account. --- # Warehouse Warehouse is the place where all the pull-flow payments in the Splits ecosystem pile up. It is built on top of [`ERC6909`](https://eips.ethereum.org/EIPS/eip-6909) and [`ERC6909X`](https://github.com/frangio/ERCs/blob/4d765d71940db25a901a592a17aa8e2a16b6efd6/ERCS/eip-xxxx.md), so all funds held here on behalf of users will appear in compliant wallets. Any user earning from the Splits ecosystem can access their assets directly from the warehouse. - [Github](https://github.com/0xSplits/splits-contracts-monorepo/tree/main/packages/splits-v2) - [Contracts & Natspec](https://github.com/0xSplits/splits-contracts-monorepo/blob/main/packages/splits-v2/src/SplitsWarehouse.sol) - [SDK](/sdk/warehouse) - [Audit](https://github.com/0xSplits/splits-contracts-monorepo/blob/main/audits/splits-v2.md) ## How it works - The warehouse has a unique id for each token. This id is the `uint256` representation of the token `address`. ETH is represented by token 0xeeee..eeee. - Deposits to the warehouse are made for a given token and user and held on their behalf until claimed. - Users can transfer their claims to these underlying tokens just like ERC20 tokens by calling the warehouse `transfer` and `transferFrom` functions. - Users who want to automate withdrawals from the warehouse may do so by setting a withdraw incentive. This will incentives bots to withdraw funds for the user directly into their account. - Users who want to prevent third parties from withdrawing on their behalf may do so by pausing their withdraws for external parties on the warehouse. - Warehouse is an immutable, non-upgradeable contract that is not owned or governed by the team. - We recommend reviewing the [contracts flow of funds](/core#flow-of-funds). ## Addresses | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://optimistic.etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :------------------------------------------------------------------------------------------------------------------------------ | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://polygonscan.com/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://basescan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://arbiscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://explorer.zora.energy/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://shapescan.xyz/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://bscscan.com/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://gnosis.blockscout.com/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://worldscan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://app.roninchain.com/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?t=contract) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://celoscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://explore.tempo.xyz/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://explorer.plume.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://abscan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://snowscan.xyz/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://holesky.etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://hoodi.etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia-optimism.etherscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.basescan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.explorer.zora.energy/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.arbiscan.io/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://www.okx.com/web3/explorer/plumenetwork-dev/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8/contract) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://saigon-app.roninchain.com/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?t=contract) | | Contract | Address | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://explore.moderato.tempo.xyz/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://testnet-explorer.plume.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8?tab=contract) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.worldscan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | | Contract | Address | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Warehouse | [`0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8`](https://sepolia.abscan.org/address/0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8#code) | --- # SplitV2 Mainnet USDT is not an ERC20 token and not compatible with Splits V2.0 or V2.1 ([learn more](https://splits.org/blog/dont-send-mainnet-usdt-to-immutable-v2-1-splits/)). SplitV2 keeps the original vision of [SplitV1](./split.mdx) while decoupling the underlying splitter implementation from where the distributed funds are held (previously `SplitMain`, now [Warehouse](./warehouse)). This decoupling allows us to build different types of splitters with different trade-offs for different use cases. At launch, we are offering "Push" and "Pull" splitters. - Create at [split.new](https://app.splits.org/new/split/) - [Github](https://github.com/0xSplits/splits-contracts-monorepo/tree/main/packages/splits-v2) - [Contracts & Natspec](https://github.com/0xSplits/splits-contracts-monorepo/tree/main/packages/splits-v2/src/splitters) - [SDK](/sdk/splits-v2) - [Audit](https://github.com/0xSplits/splits-contracts-monorepo/blob/main/audits/splits-v2.md) ## How it works - Each Split is a payable smart contract wallet. Each recipient has an address and an ownership percent. ETH and ERC20s sent directly to the Split are held in the Split's balance until `distribute` is called. - Recipients, ownerships, and keeper fees are stored onchain as calldata and re-passed as args and validated via hashing when needed. - Each Split gets its own address and proxy for maximum composability with other contracts onchain. For these proxies, we extended [EIP-1167 Minimal Proxy Contract](https://eips.ethereum.org/EIPS/eip-1167) to avoid `DELEGATECALL` inside `receive()`, allowing for Splits to accept hard gas-capped `sends` & `transfers`. - [`PullSplit`](https://github.com/0xSplits/splits-contracts-monorepo/blob/main/packages/splits-v2/src/splitters/pull/PullSplit.sol) acts very similar to the original Split the key difference being where funds pile up after distribution. All funds are held in the [Warehouse](./warehouse) after distribution. - [`PushSplit`](https://github.com/0xSplits/splits-contracts-monorepo/blob/main/packages/splits-v2/src/splitters/push/PushSplit.sol) sends funds directly to the recipients on distribution. These sends are hard gas-capped to limit the costs adversarial recipients may impose; failed sends are deposited into the [Warehouse](./warehouse). - Each Split can now also act as a smart contract wallet with the owner having full execution access from the Split's address. This allows the owner to pause distributions, make arbitrary transactions and also sign data using [`ERC1271`](https://eips.ethereum.org/EIPS/eip-1271). - We recommend reviewing the [contracts flow of funds](/core#flow-of-funds). Pull Splits do **not** work with non-transferable, fee-on-transfer, and rebasing tokens. * Non-transferable tokens will be stuck in the Split forever, unless the Split has an owner which can issue a transaction to somehow make the tokens transferable (e.g. unwrapping BLUR.) * Fee-on-transfer tokens will distribute, but not all recipients will be able to withdraw their share. * If a rebasing tokens supply decreases, not all recipients will be able to withdraw their share. If the supply increases, the incremental yield will be lost and stuck in Split Main. Push Splits do **not** work with non-transferable tokens. * Non-transferable tokens will be stuck in the Split forever, unless the Split has an owner which can issue a transaction to somehow make the tokens transferable (e.g. unwrapping BLUR.) ## Notes - When using the deterministic creation flow it is recommended to use a random salt to avoid collisions. Since these txns may technically be frontrun from the mempool, integrators should add necessary measures to handle such cases. Since the creation is deterministic, the deployed Split configuration is unaffected. Integrators can avoid this issue entirely by using `factory.createSplit` which handles salt generation onchain and cannot be frontrun. - The contracts do not impose a maximum limit on the number of recipients for a Split. Consequently, the practical limit is governed by the gas limit of the network's transactions. With the Fusaka upgrade, the transaction gas limit will be capped at [16,777,216](https://eips.ethereum.org/EIPS/eip-7825) gas units. For the above mentioned gas limit, we recommend not creating Splits with more than **400 recipients**. Be cautious of this constraint when creating large Splits, as it may result in funds being irretrievably locked due to the gas limit restrictions of the network. * When recipients have zero balance of the token. | Split | ETH | ERC20 | |-------|---------|-----------| | Push | ~16 M | ~13 M | | Pull | ~12 M | ~12 M | * When recipients have a non zero balance of the token. | Split | ETH | ERC20 | |-------|---------|-----------| | Push | ~4 M | ~3 M | | Pull | ~2 M | ~2 M | - In terms of recipient allocations, the Split creator now sets the total number of shares. As such, recipients holding small shares may be negatively impacted by rounding on small distributions, potentially leading to financial losses. For further information on this topic, please refer to [`this discussion on rounding issues`](https://github.com/zobront/audits/blob/main/reports/splits-v2.md#m-02-rounding-issues-could-allow-majority-shareholders-to-steal-funds) and [`this note on allocation size limitations`](https://github.com/zobront/audits/blob/main/reports/splits-v2.md#l-01-allocation-size-is-unbounded-which-can-cause-overflow-revert-in-getdistributions). - We do not recommend setting a Warehouse withdrawal incentive for pull Splits. Such an incentive exposes the Split to draining from a malicious actor looping withdraws & deposits. An incentive on distribution is sufficient to encourage bots to pull funds out of the Warehouse, when sufficient. or comprehensive insights, please consult this [`analysis`](https://github.com/zobront/audits/blob/main/reports/splits-v2.md#review). ## Addresses - V2.2 `PullSplits` are designed to handle non-compliant ERC20 tokens (such as Mainnet USDT) that do not return a boolean value on `approve` calls. In previous versions, this could cause transactions to fail or unexpectedly consume all available gas if an approval was missing, as described in [this issue](https://github.com/foundry-rs/foundry/issues/10884). | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://optimistic.etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://optimistic.etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://optimistic.etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://optimistic.etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------ | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://polygonscan.com/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://polygonscan.com/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://polygonscan.com/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://polygonscan.com/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://basescan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://basescan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://basescan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://basescan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://arbiscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://arbiscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://arbiscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://arbiscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://explorer.zora.energy/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://explorer.zora.energy/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://explorer.zora.energy/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://explorer.zora.energy/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://shapescan.xyz/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://shapescan.xyz/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://shapescan.xyz/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://shapescan.xyz/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://bscscan.com/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://bscscan.com/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://bscscan.com/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://bscscan.com/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://gnosis.blockscout.com/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://gnosis.blockscout.com/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://gnosis.blockscout.com/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://gnosis.blockscout.com/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://worldscan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://worldscan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://worldscan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://worldscan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://explorer.plume.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://explorer.plume.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://explorer.plume.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://explorer.plume.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://app.roninchain.com/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?t=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://app.roninchain.com/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?t=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://app.roninchain.com/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?t=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://app.roninchain.com/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?t=contract) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://celoscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://celoscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://celoscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://celoscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://explore.tempo.xyz/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://explore.tempo.xyz/address/0x1e2086A7e84a32482ac03000D56925F607CCB708) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://explore.tempo.xyz/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://explore.tempo.xyz/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://abscan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://abscan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://abscan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://abscan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://snowscan.xyz/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://snowscan.xyz/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://snowscan.xyz/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://snowscan.xyz/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://holesky.etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://holesky.etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://holesky.etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://holesky.etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://hoodi.etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://hoodi.etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://hoodi.etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://hoodi.etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia-optimism.etherscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia-optimism.etherscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia-optimism.etherscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia-optimism.etherscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.basescan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.basescan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.basescan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.basescan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.explorer.zora.energy/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.explorer.zora.energy/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.explorer.zora.energy/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.explorer.zora.energy/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.arbiscan.io/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.arbiscan.io/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.arbiscan.io/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.arbiscan.io/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://testnet-explorer.plume.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?tab=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://testnet-explorer.plume.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?tab=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://testnet-explorer.plume.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?tab=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://testnet-explorer.plume.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://saigon-app.roninchain.com/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4?t=contract) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://saigon-app.roninchain.com/address/0x1e2086A7e84a32482ac03000D56925F607CCB708?t=contract) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://saigon-app.roninchain.com/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1?t=contract) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://saigon-app.roninchain.com/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244?t=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://explore.moderato.tempo.xyz/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://explore.moderato.tempo.xyz/address/0x1e2086A7e84a32482ac03000D56925F607CCB708) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://explore.moderato.tempo.xyz/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://explore.moderato.tempo.xyz/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.worldscan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.worldscan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.worldscan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.worldscan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4`](https://sepolia.abscan.org/address/0x8E8eB0cC6AE34A38B67D5Cf91ACa38f60bc3Ecf4#code) | | PushSplit | [`0x1e2086A7e84a32482ac03000D56925F607CCB708`](https://sepolia.abscan.org/address/0x1e2086A7e84a32482ac03000D56925F607CCB708#code) | | PullSplitFactory | [`0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1`](https://sepolia.abscan.org/address/0x6B9118074aB15142d7524E8c4ea8f62A3Bdb98f1#code) | | PullSplit | [`0x98254AeDb6B2c30b70483064367f0BA24ca86244`](https://sepolia.abscan.org/address/0x98254AeDb6B2c30b70483064367f0BA24ca86244#code) | USDT on Mainnet is not an ERC20 token, which means it's not compatible with Splits V2.1. Splits V2.2 fixes this, learn more [here](https://splits.org/blog/warning-mainnet-usdt-cannot-be-distributed-from-immutable-v2-splits/). - Split factories now emit the salt passed in by the user making it easier to clone the same split on other chains. | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://optimistic.etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://optimistic.etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://optimistic.etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://optimistic.etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------ | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://polygonscan.com/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://polygonscan.com/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://polygonscan.com/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://polygonscan.com/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://basescan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://basescan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://basescan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://basescan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://arbiscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://arbiscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://arbiscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://arbiscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://explorer.zora.energy/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed?tab=contract) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://explorer.zora.energy/address/0x3f81D81e0884abD8Cc4583a704a9397972623214?tab=contract) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://explorer.zora.energy/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1?tab=contract) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://explorer.zora.energy/address/0xF9C25250523Df26343222fC46de932355B850c97?tab=contract) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://shapescan.xyz/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed?tab=contract) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://shapescan.xyz/address/0x3f81D81e0884abD8Cc4583a704a9397972623214?tab=contract) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://shapescan.xyz/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1?tab=contract) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://shapescan.xyz/address/0xF9C25250523Df26343222fC46de932355B850c97?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://bscscan.com/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://bscscan.com/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://bscscan.com/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://bscscan.com/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://gnosis.blockscout.com/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed?tab=contract) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://gnosis.blockscout.com/address/0x3f81D81e0884abD8Cc4583a704a9397972623214?tab=contract) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://gnosis.blockscout.com/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1?tab=contract) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://gnosis.blockscout.com/address/0xF9C25250523Df26343222fC46de932355B850c97?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://worldscan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://worldscan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://worldscan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://worldscan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://abscan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://abscan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://abscan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://abscan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://holesky.etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://holesky.etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://holesky.etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://holesky.etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://hoodi.etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://hoodi.etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://hoodi.etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://hoodi.etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia-optimism.etherscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia-optimism.etherscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia-optimism.etherscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia-optimism.etherscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.basescan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.basescan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.basescan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.basescan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.explorer.zora.energy/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed?tab=contract) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.explorer.zora.energy/address/0x3f81D81e0884abD8Cc4583a704a9397972623214?tab=contract) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.explorer.zora.energy/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1?tab=contract) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.explorer.zora.energy/address/0xF9C25250523Df26343222fC46de932355B850c97?tab=contract) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.arbiscan.io/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.arbiscan.io/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.arbiscan.io/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.arbiscan.io/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://www.okx.com/web3/explorer/plumenetwork-dev/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed/contract) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://www.okx.com/web3/explorer/plumenetwork-dev/address/0x3f81D81e0884abD8Cc4583a704a9397972623214/contract) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://www.okx.com/web3/explorer/plumenetwork-dev/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1/contract) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://www.okx.com/web3/explorer/plumenetwork-dev/address/0xF9C25250523Df26343222fC46de932355B850c97/contract) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.worldscan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.worldscan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.worldscan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.worldscan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xDc6259E13ec0621e6F19026b2e49D846525548Ed`](https://sepolia.abscan.org/address/0xDc6259E13ec0621e6F19026b2e49D846525548Ed#code) | | PushSplit | [`0x3f81D81e0884abD8Cc4583a704a9397972623214`](https://sepolia.abscan.org/address/0x3f81D81e0884abD8Cc4583a704a9397972623214#code) | | PullSplitFactory | [`0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1`](https://sepolia.abscan.org/address/0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1#code) | | PullSplit | [`0xF9C25250523Df26343222fC46de932355B850c97`](https://sepolia.abscan.org/address/0xF9C25250523Df26343222fC46de932355B850c97#code) | USDT on Mainnet is not an ERC20 token, which means it's not compatible with Splits V2.0. Splits V2.2 fixes this, learn more [here](https://splits.org/blog/warning-mainnet-usdt-cannot-be-distributed-from-immutable-v2-splits/). | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://optimistic.etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://optimistic.etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://optimistic.etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://optimistic.etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------ | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://polygonscan.com/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://polygonscan.com/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://polygonscan.com/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://polygonscan.com/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://basescan.org/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://basescan.org/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://basescan.org/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://basescan.org/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://arbiscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://arbiscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://arbiscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://arbiscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://explorer.zora.energy/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38?tab=contract) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://explorer.zora.energy/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34?tab=contract) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://explorer.zora.energy/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017?tab=contract) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://explorer.zora.energy/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99?tab=contract) | | Contract | Address | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://shapescan.xyz/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38?tab=contract) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://shapescan.xyz/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34?tab=contract) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://shapescan.xyz/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017?tab=contract) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://shapescan.xyz/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99?tab=contract) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://bscscan.com/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://bscscan.com/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://bscscan.com/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://bscscan.com/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://gnosis.blockscout.com/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38?tab=contract) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://gnosis.blockscout.com/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34?tab=contract) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://gnosis.blockscout.com/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017?tab=contract) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://gnosis.blockscout.com/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99?tab=contract) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://holesky.etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://holesky.etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://holesky.etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://holesky.etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://sepolia.etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://sepolia.etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://sepolia.etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://sepolia.etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://hoodi.etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://hoodi.etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://hoodi.etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://hoodi.etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://sepolia-optimism.etherscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://sepolia-optimism.etherscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://sepolia-optimism.etherscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://sepolia-optimism.etherscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://sepolia.basescan.org/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://sepolia.basescan.org/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://sepolia.basescan.org/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://sepolia.basescan.org/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | | Contract | Address | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://sepolia.explorer.zora.energy/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38?tab=contract) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://sepolia.explorer.zora.energy/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34?tab=contract) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://sepolia.explorer.zora.energy/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017?tab=contract) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://sepolia.explorer.zora.energy/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99?tab=contract) | | Contract | Address | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | PushSplitFactory | [`0xaDC87646f736d6A82e9a6539cddC488b2aA07f38`](https://sepolia.arbiscan.io/address/0xaDC87646f736d6A82e9a6539cddC488b2aA07f38#code) | | PushSplit | [`0x0285B37453F73f8dE94De0cAEf8108bC8431BE34`](https://sepolia.arbiscan.io/address/0x0285B37453F73f8dE94De0cAEf8108bC8431BE34#code) | | PullSplitFactory | [`0x80f1B766817D04870f115fEBbcCADF8DBF75E017`](https://sepolia.arbiscan.io/address/0x80f1B766817D04870f115fEBbcCADF8DBF75E017#code) | | PullSplit | [`0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99`](https://sepolia.arbiscan.io/address/0x6291497D1206618fC810900d2e7e9AF6Aa1F1b99#code) | --- # Split ![Split diagram](./img/split_diagram.png) Split acts as an equity instrument by letting you define the _percent of future value_ each recipient will earn. It's a payable smart contract that distributes all ETH & ERC20 tokens it receives among recipients according to pre-set ownership percentages. - Create at [split.new](https://app.splits.org/new/split/) - [Github](https://github.com/0xSplits/splits-contracts) - [Contracts & Natspec](https://github.com/0xSplits/splits-contracts/tree/main/contracts) - [SDK](/sdk/splits-v1) - [Example](https://app.splits.org/accounts/0xF8843981e7846945960f53243cA2Fd42a579f719/) - [Audit](https://github.com/0xSplits/splits-contracts/blob/main/audit/0xSplits_A-1.pdf) ## How it works - Each Split is a payable smart contract with two more more recipients. Each recipient has an address and an ownership percent. ETH and ERC20s sent directly to the Split are held in the Split's balance until `distributeETH` or `distributeERC20` are called. - Recipients, ownerships, and keeper fees are stored onchain as calldata and re-passed as args and validated via hashing when needed. - Each Split gets its own address and proxy for maximum composability with other contracts onchain. For these proxies, we extended [EIP-1167 Minimal Proxy Contract](https://eips.ethereum.org/EIPS/eip-1167) to avoid `DELEGATECALL` inside `receive()`, allowing for Splits to accept hard gas-capped `sends` & `transfers`. - [`SplitWallet`](https://github.com/0xSplits/splits-contracts/blob/main/contracts/SplitWallet.sol) is the implementation logic for `SplitProxy`. `SplitProxy` delegates all calls to `SplitWallet` other than handling `receive()` itself to avoid the gas cost with `DELEGATECALL`. All funds pile up in [`SplitMain`](https://github.com/0xSplits/splits-contracts/blob/main/contracts/SplitMain.sol) until `withdraw` is called for a recipient. - We recommend reviewing the [contracts flow of funds](/core#flow-of-funds). Splits do **not** work with non-transferable, fee-on-transfer, and rebasing tokens. * Non-transferable tokens will be stuck in the Split forever. * Fee-on-transfer tokens will distribute, but not all recipients will be able to withdraw their share. * If a rebasing tokens supply decreases, not all recipients will be able to withdraw their share. If the supply increases, the incremental yield will be lost and stuck in Split Main. ## Addresses | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://optimistic.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://optimistic.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x5924cD81dC672151527B1E4b5Ef57B69cBD07Eda`](https://bscscan.com/address/0x5924cD81dC672151527B1E4b5Ef57B69cBD07Eda#code) | | SplitWallet | [`0x8EfE568278b40316Ac2aebF92453A0FEcD891D7B`](https://bscscan.com/address/0x8EfE568278b40316Ac2aebF92453A0FEcD891D7B#code) | | Contract | Address | | :---------- | :---------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://gnosisscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://gnosisscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------ | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://polygonscan.com/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://polygonscan.com/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://ftmscan.com/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://ftmscan.com/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://basescan.org/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://basescan.org/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://arbiscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://arbiscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://snowtrace.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://snowtrace.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://explorer.zora.energy/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE?tab=contract) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://explorer.zora.energy/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33?tab=contract) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://aurorascan.dev/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://aurorascan.dev/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://blastscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://blastscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://celoscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://celoscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :---------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://goerli.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://goerli.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0xfC8a305728051367797DADE6Aa0344E0987f5286`](https://holesky.etherscan.io/address/0xfC8a305728051367797DADE6Aa0344E0987f5286#code) | | SplitWallet | [`0x124AFA8aE23FA2C77f3CbcE0Ca12464fE00B3D17`](https://holesky.etherscan.io/address/0x124AFA8aE23FA2C77f3CbcE0Ca12464fE00B3D17#code) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x54E4a6014D36c381fC43b7E24A1492F556139a6F`](https://sepolia.etherscan.io/address/0x54E4a6014D36c381fC43b7E24A1492F556139a6F#code) | | SplitWallet | [`0x5133d74B4bA8e0a7805a2a14BB50C9E23f50BcC9`](https://sepolia.etherscan.io/address/0x5133d74B4bA8e0a7805a2a14BB50C9E23f50BcC9#code) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://ropsten.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://ropsten.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://rinkeby.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://rinkeby.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://kovan.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://kovan.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :---------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x5924cD81dC672151527B1E4b5Ef57B69cBD07Eda`](https://testnet.bscscan.com/address/0x5924cD81dC672151527B1E4b5Ef57B69cBD07Eda#code) | | SplitWallet | [`0x8EfE568278b40316Ac2aebF92453A0FEcD891D7B`](https://testnet.bscscan.com/address/0x8EfE568278b40316Ac2aebF92453A0FEcD891D7B#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://goerli-optimism.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://goerli-optimism.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://sepolia-optimism.etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://sepolia-optimism.etherscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :---------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://testnet.ftmscan.com/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://testnet.ftmscan.com/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://blockscout.com/gnosis/chiado/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE/contracts#address-tabs) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://blockscout.com/gnosis/chiado/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33/contracts#address-tabs) | | Contract | Address | | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://testnet.snowtrace.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://testnet.snowtrace.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://mumbai.polygonscan.com/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://mumbai.polygonscan.com/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://goerli-rollup-explorer.arbitrum.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE/contracts#address-tabs) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://goerli-rollup-explorer.arbitrum.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33/contracts#address-tabs) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://testnet.aurorascan.dev/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE#code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://testnet.aurorascan.dev/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33#code) | | Contract | Address | | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://base-sepolia.blockscout.com/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE?tab=contract) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://base-sepolia.blockscout.com/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33?tab=contract) | | Contract | Address | | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://sepolia.explorer.zora.energy/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE?tab=contract) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://sepolia.explorer.zora.energy/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33?tab=contract) | | Contract | Address | | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | SplitMain | [`0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE`](https://testnet.blastscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE/contract/168587773/code) | | SplitWallet | [`0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33`](https://testnet.blastscan.io/address/0xD94c0CE4f8eEfA4Ebf44bf6665688EdEEf213B33/contract/168587773/code) | --- # Waterfall ![Waterfall diagram](./img/waterfall_diagram.png) Waterfall acts as a debt instrument by letting you specify the order in which distributions occur. It's useful when you want to pay one recipient a specific amount _before_ paying another recipient. Just like a Split, a Waterfall is a payable smart contract that is composable on both inflow and outflow. - Create at [waterfall.new](https://app.splits.org/new/waterfall/) - [Contracts & Natspec](https://github.com/0xSplits/splits-waterfall/tree/master/src) - [Github](https://github.com/0xSplits/splits-waterfall) - [SDK](/sdk/waterfall) - [Example](https://app.splits.org/accounts/0x3511373c3C78cD04C86c87628238435D7F3E6C4f/) ## How It Works - Each Waterfall is a payable smart contract with two or more tranches. Each tranche has a recipient (any payable address) and a threshold (the max number of tokens it will receive). The final tranche has no threshold and will always receive all residual tokens. - ETH and ERC20s sent to a Waterfall are stored in the contract as a balance. When the balance is distributed, each tranche sends funds to the recipient only after the preceding trance has been filled. This repeats until the all tranches have been filled, at which point all residual funds are sent to the final tranche recipient. - The Waterfall is an immutable contract—once it's been created, it cannot be changed. Funds flow unidirectionally and tranches do not reset, meaning the only way to "restart" the sequence is to create a new Waterfall. - Any non-permitted tokens sent to the Waterfall may be recovered to any of the tranche recipients. - This contract was not designed for a large number of tranches, please make sure that the total number of tranches doesn't exceed the transaction gas limit of the network. We recommend not having more than **400 tranches**. ## Addresses | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://optimistic.etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://optimistic.etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xB2641a863d9832e11181103038566752b852E7c4`](https://bscscan.com/address/0xB2641a863d9832e11181103038566752b852E7c4#code) | | Factory | [`0xB7CCCcCeb459F0910589556123dC5fA6DC8dE4E0`](https://bscscan.com/address/0xB7CCCcCeb459F0910589556123dC5fA6DC8dE4E0#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://gnosisscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://gnosisscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://polygonscan.com/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://polygonscan.com/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://ftmscan.com/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://ftmscan.com/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://basescan.org/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://basescan.org/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://arbiscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://arbiscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://snowtrace.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://snowtrace.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://explorer.zora.energy/address/0x1A1314121B06f1E358Eec90E76E459a679c88863?tab=contract) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://explorer.zora.energy/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6?tab=contract) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://aurorascan.dev/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://aurorascan.dev/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://goerli.etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://goerli.etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://holesky.etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://holesky.etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://sepolia.etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://sepolia.etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xB2641a863d9832e11181103038566752b852E7c4`](https://testnet.bscscan.com/address/0xB2641a863d9832e11181103038566752b852E7c4#code) | | Factory | [`0xB7CCCcCeb459F0910589556123dC5fA6DC8dE4E0`](https://testnet.bscscan.com/address/0xB7CCCcCeb459F0910589556123dC5fA6DC8dE4E0#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://goerli-optimism.etherscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://goerli-optimism.etherscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://testnet.ftmscan.com/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://testnet.ftmscan.com/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://blockscout.com/gnosis/chiado/address/0x1A1314121B06f1E358Eec90E76E459a679c88863/contracts#address-tabs) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://blockscout.com/gnosis/chiado/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6/contracts#address-tabs) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://testnet.snowtrace.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://testnet.snowtrace.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://mumbai.polygonscan.com/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://mumbai.polygonscan.com/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://goerli-rollup-explorer.arbitrum.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863/contracts#address-tabs) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://goerli-rollup-explorer.arbitrum.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6/contracts#address-tabs) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://testnet.aurorascan.dev/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://testnet.aurorascan.dev/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://testnet.blastscan.io/address/0x1A1314121B06f1E358Eec90E76E459a679c88863/contract/168587773/code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://testnet.blastscan.io/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6/contract/168587773/code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x1A1314121B06f1E358Eec90E76E459a679c88863`](https://sepolia.basescan.org/address/0x1A1314121B06f1E358Eec90E76E459a679c88863#code) | | Factory | [`0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6`](https://sepolia.basescan.org/address/0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6#code) | --- # Swapper ![Split diagram](./img/swapper_diagram.png) Swapper is a payable smart contract that converts all incoming tokens into a single output token. When ETH and ERC20s are received by a Swapper, they're automatically swapped into the output token according to the oracle's clearing price and the swapper's discount. If the oracle is unable to determine a clearing price (i.e., it doesn't support tokens it has received), the Swapper's owner **must** handle those tokens manually (e.g. swap or withdraw via execCalls; the former is enabled for some token-pairs by our UI). Swappers without owners will **not** be able to recover tokens received that aren't supported by their oracle. Be very careful when using immutable Swappers! - Create at [swapper.new](https://app.splits.org/new/swapper/) - [Github](https://github.com/0xSplits/splits-swapper) - [Contracts & Natspec](https://github.com/0xSplits/splits-swapper/tree/main/src) - Related: [Oracle](/core/oracle), [Diversifier](/templates/diversifier) ## How it works - Each Swapper is a payable smart contract with a beneficiary, output token (ETH or any ERC20), oracle, discount, and owner. The oracle is modular so be careful to **use a secure oracle** with sensible settings for your desired behavior. You can use whatever oracle contract you'd like. Splits currently offers two [oracles](/core/oracle): Uniswap v3 TWAP and Chainlink. - Tokens received by Swapper are held in the contract's balance until `flash` is called. When `flash` is called, the caller sends the expected amount (as determined by the oracle and discount) to the beneficiary in exchange for the balance in Swapper. This means _the caller is trading with Swapper directly_, earning the balance in exchange for sending the expected value to the beneficiary. - Each Swapper can be owned, which means the **owner has full control of the deployment**. The owner may change the beneficiary or oracle, pause the contract, and execute arbitrary transactions at their will. We recommend removing the owner or making it a multisig if Swapper is being used in any trustless setting. ```mermaid %%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'arial', 'textColor': '#6B7280', 'primaryColor': '#F3F4F6', 'primaryBorderColor': '#6B7280', 'secondaryColor': '#6EE7B7', 'secondaryBorderColor': '#047857', 'activationBorderColor': '#047857', 'tertiaryColor': '#A5B4FC', 'tertiaryBorderColor': '#4338CA' } } }%% sequenceDiagram Trader->>+SwapperIntegrator: initFlash SwapperIntegrator->>+Swapper: flash Swapper->>+Oracle: getQuoteAmounts Oracle->>-Swapper: amounts Swapper-->>SwapperIntegrator: [ transfer base token(s) ] Swapper->>+SwapperIntegrator: swapperFlashCallback SwapperIntegrator-->>Swapper: [ ERC20 approve / payback ] SwapperIntegrator->>-Swapper: Swapper-->>Beneficiary: [ transfer tokenToBeneficiary ] Swapper->>-SwapperIntegrator: totalToBeneficiary SwapperIntegrator->>-Trader: ``` ## Addresses | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://etherscan.io/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://etherscan.io/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://basescan.org/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://basescan.org/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://optimistic.etherscan.io/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://optimistic.etherscan.io/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://polygonscan.com/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://polygonscan.com/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://arbiscan.io/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://arbiscan.io/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://goerli.etherscan.io/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://goerli.etherscan.io/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x7fcdD45101E35fd626A539BA565d26A72d95fDa7`](https://sepolia.etherscan.io/address/0x7fcdD45101E35fd626A539BA565d26A72d95fDa7#code) | | Factory | [`0xa244bbe019cf1BA177EE5A532250be2663Fb55cA`](https://sepolia.etherscan.io/address/0xa244bbe019cf1BA177EE5A532250be2663Fb55cA#code) | --- # Oracle Oracle provides an interface allowing for a customization layer on top of other onchain oracles. Oracle is how [Swapper](/core/swapper) determines prices for different assets. Since Oracle itself is just an interface, most of these docs focus on the specific Oracle implementations offered by the Splits team. Currently, Splits offers two implementations, [UniV3Oracle](#univ3oracle) and [ChainlinkOracle](#chainlinkoracle). - [Github](https://github.com/0xSplits/splits-oracle) - [Contracts & Natspec](https://github.com/0xSplits/splits-oracle/tree/main/src) - Related: [Swapper](/core/swapper), [Diversifier](/templates/diversifier) ## UniV3Oracle This Oracle implementation uses [Uniswap's v3](https://docs.uniswap.org/concepts/protocol/oracle) TWAP to price assets. ### How it works ```mermaid %%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'arial', 'textColor': '#6B7280', 'primaryColor': '#F3F4F6', 'primaryBorderColor': '#6B7280', 'secondaryColor': '#6EE7B7', 'secondaryBorderColor': '#047857', 'activationBorderColor': '#047857', 'tertiaryColor': '#A5B4FC', 'tertiaryBorderColor': '#4338CA' } } }%% sequenceDiagram Alice->>+UniV3OracleImpl: getQuoteAmounts loop Every pair UniV3OracleImpl->>+UniswapV3Pools: consult UniswapV3Pools->>-UniV3OracleImpl: tick end UniV3OracleImpl->>-Alice: amounts ``` ### Default token pairs The following token pairs are supported by our default, immutable deployment of this Oracle implementation. | Token Pair | Fee | Uniswap v3 Pool | | :----------- | :---- | :-------------------------------------------------------------------------------------------------------------------------- | | (W)ETH-USDC | 0.05% | [`0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640`](https://info.uniswap.org/#/pools/0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640) | | (W)ETH-WBTC | 0.30% | [`0xCBCdF9626bC03E24f779434178A73a0B4bad62eD`](https://info.uniswap.org/#/pools/0xCBCdF9626bC03E24f779434178A73a0B4bad62eD) | | USDC-DAI | 0.01% | [`0x5777d92f208679DB4b9778590Fa3CAB3aC9e2168`](https://info.uniswap.org/#/pools/0x5777d92f208679DB4b9778590Fa3CAB3aC9e2168) | | USDC-USDT | 0.01% | [`0x3416cF6C708Da44DB2624D63ea0AAef7113527C6`](https://info.uniswap.org/#/pools/0x3416cF6C708Da44DB2624D63ea0AAef7113527C6) | | (W)ETH-USDT | 0.05% | [`0x11b815efB8f581194ae79006d24E0d814B7697F6`](https://info.uniswap.org/#/pools/0x11b815efB8f581194ae79006d24E0d814B7697F6) | | USDC-WBTC | 0.30% | [`0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35`](https://info.uniswap.org/#/pools/0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35) | | (W)ETH-UNI | 0.30% | [`0x1d42064Fc4Beb5F8aAF85F4617AE8b3b5B8Bd801`](https://info.uniswap.org/#/pools/0x1d42064Fc4Beb5F8aAF85F4617AE8b3b5B8Bd801) | | USDT-WBTC | 0.30% | [`0x9Db9e0e53058C89e5B94e29621a205198648425B`](https://info.uniswap.org/#/pools/0x9Db9e0e53058C89e5B94e29621a205198648425B) | | (W)ETH-cbETH | 0.05% | [`0x840DEEef2f115Cf50DA625F7368C24af6fE74410`](https://info.uniswap.org/#/pools/0x840DEEef2f115Cf50DA625F7368C24af6fE74410) | | (W)ETH-LINK | 0.30% | [`0xa6Cc3C2531FdaA6Ae1A3CA84c2855806728693e8`](https://info.uniswap.org/#/pools/0xa6Cc3C2531FdaA6Ae1A3CA84c2855806728693e8) | | (W)ETH-DAI | 0.30% | [`0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8`](https://info.uniswap.org/#/pools/0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8) | | (W)ETH-MATIC | 0.30% | [`0x290A6a7460B308ee3F19023D2D00dE604bcf5B42`](https://info.uniswap.org/#/pools/0x290A6a7460B308ee3F19023D2D00dE604bcf5B42) | | (W)ETH-RPL | 0.30% | [`0xe42318eA3b998e8355a3Da364EB9D48eC725Eb45`](https://info.uniswap.org/#/pools/0xe42318eA3b998e8355a3Da364EB9D48eC725Eb45) | | (W)ETH-LDO | 0.30% | [`0xa3f558aebAecAf0e11cA4b2199cC5Ed341edfd74`](https://info.uniswap.org/#/pools/0xa3f558aebAecAf0e11cA4b2199cC5Ed341edfd74) | | (W)ETH-MKR | 0.30% | [`0xe8c6c9227491C0a8156A0106A0204d881BB7E531`](https://info.uniswap.org/#/pools/0xe8c6c9227491C0a8156A0106A0204d881BB7E531) | | (W)ETH-rETH | 0.05% | [`0xa4e0faA58465A2D369aa21B3e42d43374c6F9613`](https://info.uniswap.org/#/pools/0xa4e0faA58465A2D369aa21B3e42d43374c6F9613) | | (W)ETH-sETH2 | 0.30% | [`0x7379e81228514a1D2a6Cf7559203998E20598346`](https://info.uniswap.org/#/pools/0x7379e81228514a1D2a6Cf7559203998E20598346) | | Token Pair | Fee | Uniswap v3 Pool | | :----------- | :---- | :------------------------------------------------------------------------------------------------------------------------------- | | (W)ETH-USDbC | 0.05% | [`0x4C36388bE6F416A29C8d8Eee81C771cE6bE14B18`](https://info.uniswap.org/#/base/pools/0x4c36388be6f416a29c8d8eee81c771ce6be14b18) | | (W)ETH-USDC | 0.05% | [`0xd0b53D9277642d899DF5C87A3966A349A798F224`](https://info.uniswap.org/#/base/pools/0xd0b53d9277642d899df5c87a3966a349a798f224) | | Token Pair | Fee | Uniswap v3 Pool | | :------------ | :---- | :----------------------------------------------------------------------------------------------------------------------------------- | | (W)ETH-OP | 0.30% | [`0x68f5c0a2de713a54991e01858fd27a3832401849`](https://info.uniswap.org/#/optimism/pools/0x68f5c0a2de713a54991e01858fd27a3832401849) | | (W)ETH-USDC | 0.05% | [`0x85149247691df622eaf1a8bd0cafd40bc45154a9`](https://info.uniswap.org/#/optimism/pools/0x85149247691df622eaf1a8bd0cafd40bc45154a9) | | (W)ETH-WSTETH | 0.01% | [`0x04f6c85a1b00f6d9b75f91fd23835974cc07e65c`](https://info.uniswap.org/#/optimism/pools/0x04f6c85a1b00f6d9b75f91fd23835974cc07e65c) | | (W)ETH-WBTC | 0.30% | [`0x73b14a78a0d396c521f954532d43fd5ffe385216`](https://info.uniswap.org/#/optimism/pools/0x73b14a78a0d396c521f954532d43fd5ffe385216) | | (W)ETH-DAI | 0.30% | [`0x03af20bdaaffb4cc0a521796a223f7d85e2aac31`](https://info.uniswap.org/#/optimism/pools/0x03af20bdaaffb4cc0a521796a223f7d85e2aac31) | | USDC-OP | 0.30% | [`0x1c3140ab59d6caf9fa7459c6f83d4b52ba881d36`](https://info.uniswap.org/#/optimism/pools/0x1c3140ab59d6caf9fa7459c6f83d4b52ba881d36) | | Token Pair | Fee | Uniswap v3 Pool | | :----------- | :---- | :---------------------------------------------------------------------------------------------------------------------------------- | | (W)ETH-USDC | 0.05% | [`0x45dda9cb7c25131df268515131f647d726f50608`](https://info.uniswap.org/#/polygon/pools/0x45dda9cb7c25131df268515131f647d726f50608) | | (W)ETH-WBTC | 0.05% | [`0x50eaedb835021e4a108b7290636d62e9765cc6d7`](https://info.uniswap.org/#/polygon/pools/0x50eaedb835021e4a108b7290636d62e9765cc6d7) | | (W)ETH-MATIC | 0.30% | [`0x167384319b41f7094e62f7506409eb38079abff8`](https://info.uniswap.org/#/polygon/pools/0x167384319b41f7094e62f7506409eb38079abff8) | | USDC-MATIC | 0.05% | [`0xa374094527e1673a86de625aa59517c5de346d32`](https://info.uniswap.org/#/polygon/pools/0xa374094527e1673a86de625aa59517c5de346d32) | | LINK-MATIC | 0.05% | [`0x0a28c2f5e0e8463e047c203f00f649812ae67e4f`](https://info.uniswap.org/#/polygon/pools/0x0a28c2f5e0e8463e047c203f00f649812ae67e4f) | | USDC-USDT | 0.01% | [`0xdac8a8e6dbf8c690ec6815e0ff03491b2770255d`](https://info.uniswap.org/#/polygon/pools/0xdac8a8e6dbf8c690ec6815e0ff03491b2770255d) | | USDT-MATIC | 0.05% | [`0x9b08288c3be4f62bbf8d1c20ac9c5e6f9467d8b7`](https://info.uniswap.org/#/polygon/pools/0x9b08288c3be4f62bbf8d1c20ac9c5e6f9467d8b7) | | USDC-LINK | 0.30% | [`0x94ab9e4553ffb839431e37cc79ba8905f45bfbea`](https://info.uniswap.org/#/polygon/pools/0x94ab9e4553ffb839431e37cc79ba8905f45bfbea) | | USDC-WBTC | 0.30% | [`0x847b64f9d3a95e977d157866447a5c0a5dfa0ee5`](https://info.uniswap.org/#/polygon/pools/0x847b64f9d3a95e977d157866447a5c0a5dfa0ee5) | | (W)ETH-LINK | 0.30% | [`0x3e31ab7f37c048fc6574189135d108df80f0ea26`](https://info.uniswap.org/#/polygon/pools/0x3e31ab7f37c048fc6574189135d108df80f0ea26) | | Token Pair | Fee | Uniswap v3 Pool | | :------------ | :---- | :----------------------------------------------------------------------------------------------------------------------------------- | | (W)ETH-USDCE | 0.05% | [`0xc31e54c7a869b9fcbecc14363cf510d1c41fa443`](https://info.uniswap.org/#/arbitrum/pools/0xc31e54c7a869b9fcbecc14363cf510d1c41fa443) | | (W)ETH-USDC | 0.05% | [`0xc6962004f452be9203591991d15f6b388e09e8d0`](https://info.uniswap.org/#/arbitrum/pools/0xc6962004f452be9203591991d15f6b388e09e8d0) | | (W)ETH-GMX | 1.00% | [`0x80a9ae39310abf666a87c743d6ebbd0e8c42158e`](https://info.uniswap.org/#/arbitrum/pools/0x80a9ae39310abf666a87c743d6ebbd0e8c42158e) | | (W)ETH-WBTC | 0.05% | [`0x2f5e87c9312fa29aed5c179e456625d79015299c`](https://info.uniswap.org/#/arbitrum/pools/0x2f5e87c9312fa29aed5c179e456625d79015299c) | | (W)ETH-ARB | 0.05% | [`0xc6f780497a95e246eb9449f5e4770916dcd6396a`](https://info.uniswap.org/#/arbitrum/pools/0xc6f780497a95e246eb9449f5e4770916dcd6396a) | | (W)ETH-USDT | 0.05% | [`0x641c00a822e8b671738d32a431a4fb6074e5c79d`](https://info.uniswap.org/#/arbitrum/pools/0x641c00a822e8b671738d32a431a4fb6074e5c79d) | | (W)ETH-WSTETH | 0.01% | [`0x35218a1cbac5bbc3e57fd9bd38219d37571b3537`](https://info.uniswap.org/#/arbitrum/pools/0x35218a1cbac5bbc3e57fd9bd38219d37571b3537) | | USDC-DAI | 0.01% | [`0x7cf803e8d82a50504180f417b8bc7a493c0a0503`](https://info.uniswap.org/#/arbitrum/pools/0x7cf803e8d82a50504180f417b8bc7a493c0a0503) | | USDC-USDT | 0.01% | [`0xbe3ad6a5669dc0b8b12febc03608860c31e2eef6`](https://info.uniswap.org/#/arbitrum/pools/0xbe3ad6a5669dc0b8b12febc03608860c31e2eef6) | | (W)ETH-LINK | 0.30% | [`0x468b88941e7cc0b88c1869d68ab6b570bcef62ff`](https://info.uniswap.org/#/arbitrum/pools/0x468b88941e7cc0b88c1869d68ab6b570bcef62ff) | | (W)ETH-PENDLE | 0.30% | [`0xdbaeb7f0dfe3a0aafd798ccecb5b22e708f7852c`](https://info.uniswap.org/#/arbitrum/pools/0xdbaeb7f0dfe3a0aafd798ccecb5b22e708f7852c) | | (W)ETH-RDNT | 0.30% | [`0x446bf9748b4ea044dd759d9b9311c70491df8f29`](https://info.uniswap.org/#/arbitrum/pools/0x446bf9748b4ea044dd759d9b9311c70491df8f29) | | Token Pair | Fee | | :---------- | :---- | | (W)ETH-USDC | 0.01% | | (W)ETH-DAI | 0.05% | | (W)ETH-UNI | 0.05% | | USDC-UNI | 0.30% | | Token Pair | Fee | | :---------- | :---- | | (W)ETH-USDC | 0.05% | ### Addresses | Contract | Address | | :----------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x8E0E20Ea43A88214A0908F32Cd14395022e823A6`](https://etherscan.io/address/0x8E0E20Ea43A88214A0908F32Cd14395022e823A6#code) | | UniV3OracleImpl | [`0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91`](https://etherscan.io/address/0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91#code) | | UniV3OracleFactory | [`0x498f316fEB85a250fdC64B859a130515491EC888`](https://etherscan.io/address/0x498f316fEB85a250fdC64B859a130515491EC888#code) | | Contract | Address | | :----------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x6B99b2E868B6E3B8b259E296c4c6aBffbB1AaB94`](https://basescan.org/address/0x6B99b2E868B6E3B8b259E296c4c6aBffbB1AaB94#code) | | UniV3OracleImpl | [`0x280064Ab5f49f9f61Ba9ed03a244773230beE195`](https://basescan.org/address/0x280064Ab5f49f9f61Ba9ed03a244773230beE195#code) | | UniV3OracleFactory | [`0x074827E8bD77B0A66c6008a51AF9BD1F33105caf`](https://basescan.org/address/0x074827E8bD77B0A66c6008a51AF9BD1F33105caf#code) | | Contract | Address | | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x6D55930014eCAF994B9D71a9917364f91CB20345`](https://optimistic.etherscan.io/address/0x6D55930014eCAF994B9D71a9917364f91CB20345#code) | | UniV3OracleImpl | [`0xc58F24010facB558fD9B045650077872b2Ea6B8C`](https://optimistic.etherscan.io/address/0xc58F24010facB558fD9B045650077872b2Ea6B8C#code) | | UniV3OracleFactory | [`0x73b3B74865eE1dc996Ac8EbD31C45CFb4f38e39F`](https://optimistic.etherscan.io/address/0x73b3b74865ee1dc996ac8ebd31c45cfb4f38e39f#code) | | Contract | Address | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Default Deployment | [`0x8DeF6ed1f27A02b26024C78aDcE2957d23DFD672`](https://polygonscan.com/address/0x8DeF6ed1f27A02b26024C78aDcE2957d23DFD672#code) | | UniV3OracleImpl | [`0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91`](https://polygonscan.com/address/0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91#code) | | UniV3OracleFactory | [`0x498f316fEB85a250fdC64B859a130515491EC888`](https://polygonscan.com/address/0x498f316fEB85a250fdC64B859a130515491EC888#code) | | Contract | Address | | :----------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x8DeF6ed1f27A02b26024C78aDcE2957d23DFD672`](https://arbiscan.io/address/0x8DeF6ed1f27A02b26024C78aDcE2957d23DFD672#code) | | UniV3OracleImpl | [`0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91`](https://arbiscan.io/address/0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91#code) | | UniV3OracleFactory | [`0x498f316fEB85a250fdC64B859a130515491EC888`](https://arbiscan.io/address/0x498f316fEB85a250fdC64B859a130515491EC888#code) | | Contract | Address | | :----------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x8E0E20Ea43A88214A0908F32Cd14395022e823A6`](https://goerli.etherscan.io/address/0x8E0E20Ea43A88214A0908F32Cd14395022e823A6#code) | | UniV3OracleImpl | [`0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91`](https://goerli.etherscan.io/address/0x6e65C4Be1DcD33bDddD99f42DC45B2658fe9aD91#code) | | UniV3OracleFactory | [`0x498f316fEB85a250fdC64B859a130515491EC888`](https://goerli.etherscan.io/address/0x498f316fEB85a250fdC64B859a130515491EC888#code) | | Contract | Address | | :----------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x6B99b2E868B6E3B8b259E296c4c6aBffbB1AaB94`](https://sepolia.etherscan.io/address/0x6B99b2E868B6E3B8b259E296c4c6aBffbB1AaB94#code) | | UniV3OracleImpl | [`0x280064Ab5f49f9f61Ba9ed03a244773230beE195`](https://sepolia.etherscan.io/address/0x280064Ab5f49f9f61Ba9ed03a244773230beE195#code) | | UniV3OracleFactory | [`0x074827E8bD77B0A66c6008a51AF9BD1F33105caf`](https://sepolia.etherscan.io/address/0x074827E8bD77B0A66c6008a51AF9BD1F33105caf#code) | ### Create your own We don't offer UI support for creating oracles at the moment, but technical users can fork our [default creation scripts](https://github.com/0xSplits/splits-oracle/tree/main/script) and alter appropriately to suite their needs. ## ChainlinkOracle The oracle uses Chainlink data feeds for onchain prices. Checkout the chainlink [documentation](https://docs.chain.link/data-feeds) to learn more about data feeds. ### How it works The oracle setup includes a defined path for price computation for each currency pair. The oracle maintainer configures this path, which comprises sequential steps, each containing: 1. **Feed**: This denotes the specific Chainlink oracle feed utilized to retrieve the exchange rate data. 2. **Decimals**: The scale of precision of the returned price from the feed is denoted by the decimals. It dictates the factor by which the price should be adjusted to get the actual value. 3. **StaleAfter**: A time-based parameter set by the user, which dictates the acceptable age of the data feed. If the data is older than this value, it's disregarded as stale. 4. **Mul (boolean)**: A boolean flag that determines the mathematical operation for the price adjustment. If set to true, the price from the feed is multiplied by the 'current price' in the computation path. If false, it's divided. The 'current price' is initialized to a standard base of 1 wad (1e18) to maintain precision. ### Addresses | Contract | Address | | :--------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x1Da4D514A57A78649450f3eA7D77fdBf535Ec349`](https://etherscan.io/address/0x1Da4D514A57A78649450f3eA7D77fdBf535Ec349#code) | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://etherscan.io/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://etherscan.io/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | | Contract | Address | | :--------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x750d89198220a8E4aED26e3C0a44706269cc28b7`](https://basescan.org/address/0x750d89198220a8E4aED26e3C0a44706269cc28b7#code) | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://basescan.org/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://basescan.org/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | | Contract | Address | | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0xf7D052B65959D745418D22417f3Bbe2e937a7bc0`](https://optimistic.etherscan.io/address/0xf7D052B65959D745418D22417f3Bbe2e937a7bc0#code) | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://optimistic.etherscan.io/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://optimistic.etherscan.io/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | | Contract | Address | | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Default Deployment | [`0x40ea135b07EFeA4C96275653fF933D044f8a81B0`](https://polygonscan.com/address/0x40ea135b07EFeA4C96275653fF933D044f8a81B0#code) | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://polygonscan.com/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://polygonscan.com/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | | Contract | Address | | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://arbiscan.io/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://arbiscan.io/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | | Contract | Address | | :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Default Deployment | [`0x38E9aC0d9e00f3374e77B0e88fFAb7A750045e2d`](https://sepolia.etherscan.io/address/0x38E9aC0d9e00f3374e77B0e88fFAb7A750045e2d#code) | | ChainlinkOracleImpl | [`0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb`](https://sepolia.etherscan.io/address/0x00f317A2A57B255cA81f9bD56D2521c81850e2Eb#code) | | ChainlinkOracleFactory | [`0xD28182C2E11519ad081E7fa9da711274b7096098`](https://sepolia.etherscan.io/address/0xD28182C2E11519ad081E7fa9da711274b7096098#code) | ### Create your own We don't offer UI support for creating oracles at the moment, but technical users can fork our [default creation scripts](https://github.com/0xSplits/splits-oracle/tree/main/script) and alter appropriately to suite their needs. --- # Pass-Through Wallet Pass-Through Wallet is a payable, ownable smart contract wallet with pausable token forwarding. - [Github](https://github.com/0xSplits/splits-pass-through-wallet) - [Contracts & Natspec](https://github.com/0xSplits/splits-pass-through-wallet/tree/main/src) - Related: [Diversifier](/templates/diversifier) ## How it works - Funds are held in the contract's balance until `passThroughTokens` is called. At any time the owner may pause `passThroughTokens`, update the pass-through address, or execute arbitrary calls from the Pass-Through Wallet. ```mermaid %%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'arial', 'textColor': '#6B7280', 'primaryColor': '#F3F4F6', 'primaryBorderColor': '#6B7280', 'secondaryColor': '#6EE7B7', 'secondaryBorderColor': '#047857', 'activationBorderColor': '#047857', 'tertiaryColor': '#A5B4FC', 'tertiaryBorderColor': '#4338CA' } } }%% sequenceDiagram Alice->>+PassThroughWallet: passThroughTokens PassThroughWallet-->>PassThrough: [ transfer tokens ] PassThroughWallet->>-Alice: amounts ``` ## Addresses | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xfE87400C401C0CB61EC3a923a5d9873090e8daFc`](https://etherscan.io/address/0xfE87400C401C0CB61EC3a923a5d9873090e8daFc#code) | | Factory | [`0xF5aCC1568706Fbf9A55a77DdBe8DF907Da95dD6B`](https://etherscan.io/address/0xF5aCC1568706Fbf9A55a77DdBe8DF907Da95dD6B#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc`](https://basescan.org/address/0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc#code) | | Factory | [`0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40`](https://basescan.org/address/0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc`](https://optimistic.etherscan.io/address/0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc#code) | | Factory | [`0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40`](https://optimistic.etherscan.io/address/0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc`](https://polygonscan.com/address/0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc#code) | | Factory | [`0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40`](https://polygonscan.com/address/0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc`](https://arbiscan.io/address/0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc#code) | | Factory | [`0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40`](https://arbiscan.io/address/0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xfE87400C401C0CB61EC3a923a5d9873090e8daFc`](https://goerli.etherscan.io/address/0xfE87400C401C0CB61EC3a923a5d9873090e8daFc#code) | | Factory | [`0xF5aCC1568706Fbf9A55a77DdBe8DF907Da95dD6B`](https://goerli.etherscan.io/address/0xF5aCC1568706Fbf9A55a77DdBe8DF907Da95dD6B#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc`](https://sepolia.etherscan.io/address/0xf62d6eBbc108b8B16218Dbf8FC0e249BA9fBb4bc#code) | | Factory | [`0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40`](https://sepolia.etherscan.io/address/0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40#code) | --- # Vesting ![Vesting diagram](./img/vesting_diagram.png) Vesting allows multiple, isolated streams of tokens to vest to an address over a set period of time. All streams within the contract share a vesting period, but each stream may begin vesting or release tokens independently. - [Contracts & NatSpec](https://github.com/0xSplits/splits-vesting/tree/master/src) - [Github](https://github.com/0xSplits/splits-vesting) - [SDK](/sdk/vesting) - [Example](https://app.splits.org/accounts/0xF29Ff96aaEa6C9A1fBa851f74737f3c069d4f1a9/) ## How It Works - Each Vesting is a payable smart contract with a vesting period and a recipient. ETH and ERC20s sent to Vesting are held until a token-specific vesting stream is started. Multiple vesting streams may exist simultaneously within Vesting. - Once a vesting stream has begun, tokens in that stream will vest linearly and all tokens will be 100% vested by the end of the vesting period. At any time, anyone may release the vested portion to the recipient. - Since Vesting is immutable, it's designed to be used in conjunction with a mutable Split or any contract that can be modified. Vesting funds to an immutable contract is equivalent to sending all tokens at once, since there is no way to revoke a stream or remove funds within a Vesting before a stream has begun. - It is unnecessary to duplicate a Vesting that already exists, therefore each Vesting must have a unique combination of vesting period and recipient. ## Addresses | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://optimistic.etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://optimistic.etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x775B6e1CBcA6149875355e64450aAd9e645e6c2D`](https://bscscan.com/address/0x775B6e1CBcA6149875355e64450aAd9e645e6c2D#code) | | Factory | [`0x7205d93721837c45Be23C930D9fba842e968Ad69`](https://bscscan.com/address/0x7205d93721837c45Be23C930D9fba842e968Ad69#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://gnosisscan.io/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://gnosisscan.io/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://polygonscan.com/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://polygonscan.com/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://ftmscan.com/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://ftmscan.com/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://basescan.org/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://basescan.org/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://arbiscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://arbiscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://snowtrace.io/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://snowtrace.io/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://explorer.zora.energy/address/0x652a2a2876b855d9c30d9265f882f0a486608976?tab=contract) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://explorer.zora.energy/address/0x0a2841630f198745a55c4dab3fe98f77271949e5?tab=contract) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://aurorascan.dev/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://aurorascan.dev/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://celoscan.io/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://celoscan.io/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://goerli.etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://goerli.etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://holesky.etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://holesky.etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://sepolia.etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://sepolia.etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x775B6e1CBcA6149875355e64450aAd9e645e6c2D`](https://testnet.bscscan.com/address/0x775B6e1CBcA6149875355e64450aAd9e645e6c2D#code) | | Factory | [`0x7205d93721837c45Be23C930D9fba842e968Ad69`](https://testnet.bscscan.com/address/0x7205d93721837c45Be23C930D9fba842e968Ad69#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://goerli-optimism.etherscan.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://goerli-optimism.etherscan.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://testnet.ftmscan.com/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://testnet.ftmscan.com/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://blockscout.com/gnosis/chiado/address/0x652a2A2876B855d9c30d9265F882F0a486608976/contracts#address-tabs) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://blockscout.com/gnosis/chiado/address/0x0a2841630f198745a55C4dab3fE98f77271949E5/contracts#address-tabs) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://testnet.snowtrace.io/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://testnet.snowtrace.io/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://mumbai.polygonscan.com/address/0x652a2a2876b855d9c30d9265f882f0a486608976#code) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://mumbai.polygonscan.com/address/0x0a2841630f198745a55c4dab3fe98f77271949e5#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2a2876b855d9c30d9265f882f0a486608976`](https://goerli-rollup-explorer.arbitrum.io/address/0x652a2a2876b855d9c30d9265f882f0a486608976/contracts#address-tabs) | | Factory | [`0x0a2841630f198745a55c4dab3fe98f77271949e5`](https://goerli-rollup-explorer.arbitrum.io/address/0x0a2841630f198745a55c4dab3fe98f77271949e5/contracts#address-tabs) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x652a2A2876B855d9c30d9265F882F0a486608976`](https://testnet.aurorascan.dev/address/0x652a2A2876B855d9c30d9265F882F0a486608976#code) | | Factory | [`0x0a2841630f198745a55C4dab3fE98f77271949E5`](https://testnet.aurorascan.dev/address/0x0a2841630f198745a55C4dab3fE98f77271949E5#code) | --- # Templates This section describes more complicated payment flows that are built by composing multiple building blocks. --- # Recoup ![Recoup diagram](./img/recoup_diagram.png) The Recoup template allows you to split profits instead of revenue. By creating a [Waterfall](/core/waterfall) that points to a number of [Splits](/core/split), it makes it easy to repay one group before splitting profits with another. - [Creation form](https://app.splits.org/new/recoup/) - [Contracts & NatSpec](https://github.com/0xSplits/splits-recoup/tree/main/src) - [Github](https://github.com/0xSplits/splits-recoup) - [SDK](/sdk/templates) - [Example](https://app.splits.org/accounts/0x0bb7a1B75Ac3e679d77E5336fDEBcFe95E89cEED/) ## How It Works - We recommend familiarizing yourself with how [Waterfall](/core/waterfall) and [Split](/core/split) work, since Recoup is just a factory to make it easier to deploy those building blocks composed together in a single transaction. - Any non-target tokens sent to the Recoup will be recovered to the final tier (i.e., the profit share tier). - This contract was not designed for a large number of tranches, please make sure that the total number of tranches doesn't exceed the transaction gas limit of the network. We recommend not having more than **400 tranches**. ## Addresses | Contract | Address | | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://etherscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://optimistic.etherscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0x5ff0C88311F79803B43e9Dc3F2B20F49A6b680fd`](https://bscscan.com/address/0x5ff0C88311F79803B43e9Dc3F2B20F49A6b680fd#code) | | Contract | Address | | :------- | :---------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://gnosisscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------ | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://polygonscan.com/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://ftmscan.com/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://basescan.org/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://arbiscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://snowtrace.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://explorer.zora.energy/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41?tab=contract) | | Contract | Address | | :------- | :----------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://aurorascan.dev/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://goerli.etherscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xcFba37C5Ee4d80c286593342470EB881deb9799e`](https://holesky.etherscan.io/address/0xcFba37C5Ee4d80c286593342470EB881deb9799e#code) | | Contract | Address | | :------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0x8Cbb4e187ce8A29BACC13Fd999a107f3c4b46D3B`](https://sepolia.etherscan.io/address/0x8Cbb4e187ce8A29BACC13Fd999a107f3c4b46D3B#code) | | Contract | Address | | :------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0x5ff0C88311F79803B43e9Dc3F2B20F49A6b680fd`](https://testnet.bscscan.com/address/0x5ff0C88311F79803B43e9Dc3F2B20F49A6b680fd#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://goerli-optimism.etherscan.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://testnet.ftmscan.com/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://blockscout.com/gnosis/chiado/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41/contracts#address-tabs) | | Contract | Address | | :------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://testnet.snowtrace.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://mumbai.polygonscan.com/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://goerli-rollup-explorer.arbitrum.io/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41/contracts#address-tabs) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Recoup | [`0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41`](https://testnet.aurorascan.dev/address/0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41#code) | --- # Liquid Split ![Liquid Split diagram](./img/liquid_diagram.png) Unlike standard Splits where ownership is manually controlled, Liquid Splits use NFTs to make ownership transferable. This allows each recipient to control their share of the Split themselves. This template uses an ERC-1155 NFT contract and a mutable [Split](/core/split). You can integrate Liquid Splits into your own NFT project (including adding your own artwork etc) by forking [this repo](https://github.com/0xSplits/splits-liquid-template). - [Creation form](https://app.splits.org/new/split/?type=liquid) - [Contracts & NatSpec](https://github.com/0xSplits/splits-liquid/tree/master/src) - [Github](https://github.com/0xSplits/splits-liquid) - [Integration Template](https://github.com/0xSplits/splits-liquid-template) - [SDK](/sdk/liquid) - [App Example](https://app.splits.org/accounts/0x8427e46826a520b1264B55f31fCB5DDFDc31E349/) - Related: [Split](/core/split), [ERC-1155](https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/) When adding this functionality to your contracts, if `sum(percentAllocations) != 1e6` the Split will fail to update and funds will be stuck! Be careful when managing supply (including burns, rounding on odd numbers, etc). For this reason there is no burn function exposed in our implementation. ## How It Works - When a Liquid Split is created, an ERC-1155 contract is deployed and 1,000 NFTs are minted to the initial recipients with each recipient receiving their share of the NFTs. The ERC-1155 contract is then set as the controller for a mutable Split. Funds pile up in the Liquid Split contract (which is the ERC-1155 contract) and whenever a balance is distributed the NFT contract updates the Split to match current NFT holders and immediately distributes the balance. This is done by calling [`updateAndDistribute`](https://github.com/0xSplits/splits-contracts/blob/main/contracts/SplitMain.sol#L410). - NFTs should only be considered to represent funds that _have not yet been received by the Liquid Split_. Because recipients of a Liquid Split are updated at the time of a distribution, it is unsafe to assume that acquiring Liquid Split NFTs will entitle someone to any portion of the current balance. A seller could easily distribute the balance right before transferring you the shares, causing them to receive that portion of the balance. - We recommend setting the distribution incentive on Liquid Splits to be slightly higher (i.e., ~2-3% instead of ~1%). This is because distributions require more gas given the need to both update and distribute the Split. - The ERC-1155 standard was used since it allows batch transfers. This means that someone can transfer 1% of the Split (10 NFTs) in a single transaction instead of 10 separate ones (which would be required if using the ERC-721 standard). - The new [Fusaka upgrade](https://ethereum.org/roadmap/fusaka/#transaction-gas-limit-cap) introduces a transaction gas limit of 16,777,216 (2^24). We recommend not creating Liquid Splits with more than **500 recipients** to avoid running into the gas limit when distributing funds. ## Addresses | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://etherscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://etherscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://optimistic.etherscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://optimistic.etherscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x306306EB890B79bA98CFF84a1637e2B64c4092b4`](https://bscscan.com/address/0x306306EB890B79bA98CFF84a1637e2B64c4092b4#code) | | Factory | [`0xCDe071bE119024EdC970B3Da15003ee834ae40D2`](https://bscscan.com/address/0xCDe071bE119024EdC970B3Da15003ee834ae40D2#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://gnosisscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://gnosisscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://polygonscan.com/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://polygonscan.com/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://ftmscan.com/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://ftmscan.com/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://basescan.org/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://basescan.org/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://arbiscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://arbiscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://snowtrace.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://snowtrace.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://explorer.zora.energy/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371?tab=contract) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://explorer.zora.energy/address/0xdecd8b99b7f763e16141450daa5ea414b7994831?tab=contract) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://aurorascan.dev/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://aurorascan.dev/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://goerli.etherscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://goerli.etherscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xe46171517E9C93EfB2938a1C4d783fCC8B76896b`](https://holesky.etherscan.io/address/0xe46171517E9C93EfB2938a1C4d783fCC8B76896b#code) | | Factory | [`0xAbA0E852f1EB10196b55f877903A87a2588b7aa8`](https://holesky.etherscan.io/address/0xAbA0E852f1EB10196b55f877903A87a2588b7aa8#code) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x8dAe40bd08E2Ff7d4077cfDbb7C11C90fc884D25`](https://sepolia.etherscan.io/address/0x8dAe40bd08E2Ff7d4077cfDbb7C11C90fc884D25#code) | | Factory | [`0xb3Af150A5902e06373A2D3f177d85435A48c6b33`](https://sepolia.etherscan.io/address/0xb3Af150A5902e06373A2D3f177d85435A48c6b33#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0x306306EB890B79bA98CFF84a1637e2B64c4092b4`](https://testnet.bscscan.com/address/0x306306EB890B79bA98CFF84a1637e2B64c4092b4#code) | | Factory | [`0xCDe071bE119024EdC970B3Da15003ee834ae40D2`](https://testnet.bscscan.com/address/0xCDe071bE119024EdC970B3Da15003ee834ae40D2#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://goerli-optimism.etherscan.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://goerli-optimism.etherscan.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://testnet.ftmscan.com/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://testnet.ftmscan.com/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://blockscout.com/gnosis/chiado/address/0xB7d1Fd59f072509AE4e2Eb0628805524B2476371/contracts#address-tabs) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://blockscout.com/gnosis/chiado/address/0xdEcd8B99b7F763e16141450DAa5EA414B7994831/contracts#address-tabs) | | Contract | Address | | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://testnet.snowtrace.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://testnet.snowtrace.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://mumbai.polygonscan.com/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://mumbai.polygonscan.com/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://goerli-rollup-explorer.arbitrum.io/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371/contracts#address-tabs) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://goerli-rollup-explorer.arbitrum.io/address/0xdecd8b99b7f763e16141450daa5ea414b7994831/contracts#address-tabs) | | Contract | Address | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | Implementation | [`0xb7d1fd59f072509ae4e2eb0628805524b2476371`](https://testnet.aurorascan.dev/address/0xb7d1fd59f072509ae4e2eb0628805524b2476371#code) | | Factory | [`0xdecd8b99b7f763e16141450daa5ea414b7994831`](https://testnet.aurorascan.dev/address/0xdecd8b99b7f763e16141450daa5ea414b7994831#code) | --- # Diversifier ![Split diagram](./img/diversifier_diagram.png) Diversifier is a smart contract that automatically diversifies an income stream into specific tokens of various ratios. This is particularly useful for tax withholdings, for example when you want to automatically swap 40% of your income into a stablecoin and set aside for taxes. This template simply stacks a [Pass-Through Wallet](/core/pass-through) on top of a [Split](/core/split) on top of a number of [Swappers](/core/swapper). - [Creation form](https://app.splits.org/new/diversifier/) - [Github](https://github.com/0xSplits/splits-diversifier) - [Contracts & Natspec](https://github.com/0xSplits/splits-diversifier/tree/main/src) - Related: [Split](/core/split), [Swapper](/core/swapper), [Pass-Through Wallet](/core/pass-through) ## How it works - Each Diversifier is a payable smart contract that uses a Split to automatically split incoming tokens according to pre-set percentages. Recipients of the Split may be Swappers to automatically swap tokens into a specified output tokens. A Pass-Through Wallet sits on top and owns / controls all of the underlying modules, allowing the Diversifier to function as a full wallet. That's all there is to it, so if that sounds complicated we recommend you review the Split, Swapper, and Pass-Through Wallet contracts. - Each Diversifier can be owned, which means the owner has full control of the deployment. The owner may modify the Split, change the oracles and discounts, pause the Swappers, and execute arbitrary transactions at their will. We recommend removing the owner or making it a multisig if this contract is being used in any trustless setting. ```mermaid %%{ init: { 'theme': 'base', 'themeVariables': { 'fontFamily': 'arial', 'lineColor': '#6B7280', 'textColor': '#6B7280', 'primaryColor': '#F3F4F6', 'primaryBorderColor': '#6B7280', 'secondaryColor': '#6EE7B7', 'secondaryBorderColor': '#047857', 'activationBorderColor': '#047857', 'tertiaryColor': '#A5B4FC', 'tertiaryBorderColor': '#4338CA' } } }%% flowchart PassThroughWallet --> Split Split --> Recipient1 Split --> Swapper2 Split --> Swapper3 Swapper2 --> Recipient2 Swapper3 --> Recipient3 ``` ## Addresses | Contract | Address | | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x78791997483f25217F4C3FE2a568Fe3eFaf77884`](https://etherscan.io/address/0x78791997483f25217F4C3FE2a568Fe3eFaf77884#code) | | Contract | Address | | :------- | :--------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x1f3f5C7342Ae19E2b35b657864106f227201eF8A`](https://basescan.org/address/0x1f3f5C7342Ae19E2b35b657864106f227201eF8A#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x1f3f5C7342Ae19E2b35b657864106f227201eF8A`](https://optimistic.etherscan.io/address/0x1f3f5C7342Ae19E2b35b657864106f227201eF8A#code) | | Contract | Address | | :------- | :------------------------------------------------------------------------------------------------------------------------------ | | Factory | [`0x1f3f5C7342Ae19E2b35b657864106f227201eF8A`](https://polygonscan.com/address/0x1f3f5C7342Ae19E2b35b657864106f227201eF8A#code) | | Contract | Address | | :------- | :-------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x1f3f5C7342Ae19E2b35b657864106f227201eF8A`](https://arbiscan.io/address/0x1f3f5C7342Ae19E2b35b657864106f227201eF8A#code) | | Contract | Address | | :------- | :---------------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x78791997483f25217F4C3FE2a568Fe3eFaf77884`](https://goerli.etherscan.io/address/0x78791997483f25217F4C3FE2a568Fe3eFaf77884#code) | | Contract | Address | | :------- | :----------------------------------------------------------------------------------------------------------------------------------- | | Factory | [`0x0eAeAfD1c82563B6005c7D09031462D9FF68Adab`](https://sepolia.etherscan.io/address/0x0eAeAfD1c82563B6005c7D09031462D9FF68Adab#code) |