PaymentSplitter.sol, modified to tokenize the right to pull from the Payment Splitter

Hello OpenZeppelin Community!

First of all, as someone who is new to code, many thanks to the OpenZeppelin team and everybody who has contributed to the creation of such elegant and useful Smart Contracts.

I am excited at the prospect of contributing to the community's efforts and hope to add value.

PaymentSplitter.sol is the first Smart Contract that I have made meaningful modifications to.



The stated purpose of the original Payment Splitter Smart Contract is to allow proceeds from projects to be split between its contributing members. It accomplishes this by (i) creating an address that can accept the funds, and then (ii) allowing whitelisted addresses to pull funds from this address.

The issue is that the addresses that can pull from the Payment Splitter Smart Contract need to be whitelisted on deployment. Furthermore, the proportion of funds due to every whitelisted member also needs to be inputted at time of deployment.


This obviously limits the capacity of the Payment Splitter Smart Contract. In any project, both the make up of members and the subsequent splits due to each member is subject to change.

I understand that the Payment Splitter Smart Contract is Ownable, and therefore the contract can be modified to give the Owner permission to make changes to whitelist memberships and splits, and to even add new addresses to the whitelist.

However, let's imagine a case where four parties decide to launch a project together where each party is considered to be equal. In this case, who gets to be the Owner of the Payment Splitter contract that receives proceeds for the project?

And what happens if one of the four parties decides they do not want to be involved anymore and therefore wants to sell what is effectively their ownership in the project as manifest in their right to claim proceeds?


The first thing we want to do is tokenize the right to pull proceeds from the Payment Splitter contract.

This enables any party that is due proceeds from the Payment Splitter to be able pull them without being tied to a specific wallet address. This also provides the added benefit of giving the parties the choice to sell or speculate on their position regarding the proceeds they may receive from the project. On the other side, it enables those who want to buy into a project the means to realize said desire.

I have tokenized the position (i.e. the right to pull proceeds) by making it such that the modified Payment Splitter Smart Contract receives an ERC-721 NFT Address in the constructor for deployment rather than a set of whitelisted addresses accompanied by a corresponding set of splits.

Only those who hold an NFT minted from the inputted NFT Address has the right to pull from the Smart Contract. This NFT Address needs to have a cap to its Total Supply. The amount due is equal for all minted NFTs at 1/N where N = Total Supply. However, it is possible for one address to hold more than one of these ownership NFTs and therefore pull X/N from the Payment Splitter where X = number of NFTs held.

The modified Payment Splitter tracks the amount due to each position by tying it the TokenID of each NFT. An NFT token that has already been used to pull funds from the Payment Splitter contract will only be able to pull their share of new incoming funds into the Payment Splitter. This is obviously necessary for the integrity of the Payment Splitter.

This solution accommodates shifts within the membership of a project, and shifts in the splits due to each member. Of course, this does not mean that all ugly situations will be avoided. However, the tokenization of the position at least provides the necessary means to execute a solution at the technical level. This is better than having to deploy a whole new Payment Splitter in every instance that there is a shift, which in some cases may require the project itself to have to redeploy.


Instead of using NFTs, we can adjust the Payment Splitter contract to be designed around an ERC-20 token contract. In this case, holding the designated ERC-20 tokens would give the holder the right to pull funds from the Payment Splitter contract in proportion to their ownership stake over the total supply of ERC-20 tokens.

This carries certain advantages since ERC-20 tokens can be fractionalized and have certain utilities that come with being fungible; for example, applications in DeFi.

However, my goal here is to mirror a Board of Directors. For a Board, positions are more limited and identifiable, and therefore carry greater accountability and prestige. This is (one reason) why LA Lakers is owned by a limited number of entities rather than offering Common Stock to any person on the street. In scarcity, there is prestige, and also accountability.

NFTs do a much better job of producing these effects than ERC-20 tokens, which are impersonal and are rarely used to demonstrate clout.

In general, and as the industry continues to evolve, projects should have a two tiered ownership / management structure where ERC-721s are used to function as Board seats and ERC-20s are used to vote on governance matters.

Despite what Carl "the Goat" Icahn would have us believe, Boards exist because they provide useful oversight and accountability. Providing a technical means for a Board to exist for the crypto projects will provide tangible value moving forward.


If you look at my GitHub repo, provided above, there are two Smart Contracts: Payment.sol and Payment_Account.sol.

Payment.sol requires that any party requesting to pull funds from the Payment Splitter to input a TokenID from the NFT collection tied the Payment Splitter. The contract then checks to see whether or not the party holds the corresponding TokenID, and then releases funds to the party only if the TokenID is in the party's wallet.

Payment_Account.sol automatically checks if the party wishing to pull funds from the Payment Splitter holds any NFTs from the NFT collection tied to the Payment Splitter. If the party holds X/N of the NFTs, then the Payment Splitter will send X/N of the proceeds to the party; if the party holds 0, then the Payment Splitter sends nothing.

Although Payment_Account.sol provides a better user experience, it is slower and more expensive, likely because the way I wrote the Smart Contract is not as elegant as it could be.


It is clear the modified Payment Splitter has other utilities; for example, token airdrops for NFT collections.

Since both variations basically built entirely on the original Payment Splitter, basically only adjusting address[] private _payees to TrunkNFT internal nft where TrunkNFT is a standard ERC-721 contract, I do not foresee any major security issues that are not presented in the original Payment Splitter. Nonetheless, an extra review never hurts.


Hi, welcome to the community! :wave:

Sounds like great.

Maybe you can set the owner to a Multi-Signature Wallet, such as gnosis-safe