Partial Common Ownership of NFT Standards

Starting a topic to discuss standards and implementations around partial common ownership of NFTs.

Some thoughts on my mind:

  • What solutions exist for partial common ownership of ERC721 + NFTs?
  • What are the tradeoffs these different solutions have, decided on, and why?
  • Should/why/how can we create a new standard around NFTs under partial common ownership?

Geo Web Solutions

So far, we have experimented with two different implementations on the Geo Web.

Initial Prototype

  • “Admin” is separate from ERC721 and has permission to make transfers
  • Approval of others to transfer is disabled (meant to disable sales on other marketplaces)
  • Admin stores expiration and self-assessed value of each asset
  • Deposits cannot be withdrawn, but new owner must pay the deposit to the old owner
  • Collecting fees is a constant time operation, as the beneficiary’s deposit is stored instead of all asset owners
  • Upon expiration, the asset is put up for a dutch auction, with the price decreasing to 0 over some amount of time

Current Solution

Similar to above except:

  • Admin is separated into more modular components (Accountant, ETHExpirationCollector, ETHPurchaser, SimpleETHClaimer)
  • Approvals are no longer disabled
  • Accountant stores fee rate instead of self-assessed value (allows for change to tax rate without re-calculating every asset’s value)

Other Solutions

Other solutions I have come across.

721 Labs

Some quick notes (may not be accurate):

  • All logic is in a single ERC721 contract
  • Stores price/value of asset
  • Owners have a deposit, which can be withdrawn
    • Foreclosure time is calculated from deposit
  • Tax collection is triggered on any action taken on an asset or manually
    • Buy, price change, deposit, withdrawal
  • Disables traditional ERC721 transfers
  • Stores a chain of title transfer events

Wild Cards

Superfluid (Streaming Payments)

1 Like


Adding thoughts to the aforementioned solutions.

Geo Web

going to return to this because you’ve clearly spent some time on it

721 Labs

  1. This is me so I can speak to it most directly.
  2. The contract is forked from Simon DLR’s This Artwork Is Always On Sale v2 which uses a deposit to ensure that the Harberger tax is be paid out, rather than potentially waiting to deduct the tax from the next sale. This should decrease the propensity to rent-seek e.g. preventing the asset owner from setting an absurdly high price in the scenario that they don’t want to sell b/c the asset provides non-monetary value.
  3. Unfortunately I didn’t document my rational for forking from Simon rather than Wildcards.
  4. The contract is designed to represent a Partially Commonly owned ERC721 asset with no other contractual dependencies outside of OpenZeppelin’s ERC721.sol. For now this asset, for now, must be deployed from scratch. I am thinking about developing / deploying an ERC1155 contract for wrapping existent NFTs to make them PCO but am not sure whether that should be included within the core repo for 721 Lab’s implementation.
  5. I modified it to push the Harberger tax rather than have it pulled, which goes against best practices [1] and requires whoever calls the tax collection method to pay the additional tax for transferring the funds. I decided this because, I believe the burden should not rely on the beneficiary to collect their tax, although this is a weakly held belief. Ultimately, I think an off-chain cronjob should trigger tax collection periodically and some percentage of the funds remitted to the beneficiary should be redirected to a wallet to pay these gas fees.

Wild Cards

  1. Implementation is very close to Simon’s v1 (they clearly share some code) with some additional management logic (e.g. #listNewTokens).


  1. I spent the better half of a day a) playing with the SF web app and b) trying to grok their contracts and there’s so logic proprietary to their application layer within the contracts that it was difficult and I found myself walking forward from the first commit because architectural documentation is non-existent.
  2. Streaming the Harberger tax from the wallet of the asset’s steward to the beneficiary’s wallet is optimal b/c it doesn’t require the steward to possess more funds than their purchase price at the time of purchase (unlike the deposit system used by 721). Unfortunately, I don’t understand the Superfluid architecture well enough to comment on its feasibility for use in a token standard. I do know that they require a deposit equal to the amount being streamed, which negates these benefits.


  1. It appears that, rather than applying taxation over time, the final sale price is reduced proportionally to the taxes owed (Nonomos does this as well). As alluded to in 721 #2, I believe this increases the incentive for rent seeking and decreases efficacy of the taxation.
  2. I see #buyToken in Seller.sol – not sure if this is a perpetual market or the current owner needs to list “for sale”. The inline method comment alludes to the latter but I couldn’t tell from my first pass over the method logic.

Open Questions / Tradeoffs

  • When should the Harberger Tax be collected and how? Should it be remitted (push) to the beneficiary or should the beneficiary collect it (pull)? Who should pay associated gas fees?
  • All of the solutions hard code the tax rate: how should the turnover rate be measured in order to set the tax rate so that the contradictory incentives to over- and under- assess the asset’s value fall into equipoise? Should this be a concern of the token or be left up to another layer (either at the protocol or application level)?

A New Standard

I believe that we should create a standard implementation for several reasons:

  • It lowers the barrier to entry for new comers to experiment with Partial Common Ownership which should ultimately result in more real-world applications, trial-and-error, refinements, and more socially optimal outcomes.
  • Working collectively on a standard is a faster and less expensive way path to robust production-level code quality, documentation, tests, security, etc. for all of us and should decrease our tail risks of something going catastrophically wrong and sinking any individual projects.
  • There are few (perhaps none, outside of paying off-chain taxes) deflationary incentives in the NFT ecosystem currently and we are experiencing an asset-price bubble. Short of the US passing a wealth tax and applying it to crypto holdings, I don’t foresee major DAOs (which are effectively and arbitrarily setting the ceiling prices for the entire NFT market) selling off their holdings any time soon – why would they? Much of the current rent-seeking behavior is a sub-optimal allocation of Eth away from more productive ends which would benefit the ecosystem as a whole and create more economic value for all of us. In this light, I see PCO entering the zeitgeist as a net benefit towards popping this bubble – I am personally interested in a Harberger-taxed DAO that is more competitive than other DAOs because it’s forced to make optimally productive investments and starts a paper hands cascading effect throughout the ecosystem.
1 Like

This is great. Thanks for all the info @will!

Some more info shared by @graven that I did not mention in my first post. We have also discussed an implementation for the beneficiary to collect (pull) accrued taxes in constant* time, regardless of the number of assets who’s taxes are going to that beneficiary.

We have a few meetings setup with various people in RxC community interested in partial common ownership. As mentioned in Discord, we will probably find another place to continue this conversation across multiple people and teams.

I will come back to this thread after those conversations and update it with relevant info for the Geo Web.

*Update: I meant constant, not linear


Something like this?

function withdrawFunds() public {
  // query all tokens the message sender is beneficiary of
  uint256[] beneficiaryOf = getTokensOf(msg.sender);

  // map & reduce
  uint256 remittance = 0;
  for (uint i = 0; i< beneficiaryOf.length; i++) {
    uint256 tokenId = beneficiaryOf[i];
    uint256 due = getTaxedOwed(tokenId);
    remittance += due;


It probably makes the most sense, for now, to use this as Geo Web’s Partial Common Ownership thread.

Our goal is to withdraw without iterating through all tokens that the DAO is a beneficiary of, since the DAO would be the single beneficiary for all tokens in our case. We want this to be a constant and not linear time operation.

However, I can see where there are other use cases when it may be perfectly acceptable to iterate through all tokens. Like when an artist wants to collect funds from each of their pieces, or whenever else there may be a small number of tokens for one beneficiary. I believe Wild Cards fits this use case.

Because in your case Geo Web (the Geo Web DAO?) is the always beneficiary, correct?

Something as simple as?

private uint256 balance = 0;
address payable owner;

function collectTax() public payable {
  balance += msg.value;

function withdrawFunds() public ownerOnly {
  balance = 0;

That is essentially what we have implemented today. What @graven discusses in that post is how to only collect taxes that have actually accrued, so not the entire msg.value.

Say a user deposits 1 ETH for a parcel worth 10 ETH. At 10% tax rate, that deposit is enough to pay for a year of taxes. The DAO could either:

  1. Collect the entire 1 ETH now and put in treasury (what we have today)
  2. Collect 1 ETH over the course of a year. So after the first month, the DAO can collect only 1/12 ETH

Makes sense. The latter is what my implementation has because the tax holder can withdraw. A few things come to mind:

  • What stops the DAO from spending the deposit and then, before the year is over, the owner wants to exit their plot? Are they refunded their deposit from the DAO’s treasury? If so, what if there are no sufficient funds to cover i.e. misallocation of the DAO’s treasury.
  • The deposit should be put into an asset with a high probability of being productive so that the depositor does not incur an opportunity cost (e.g. IRL receiving back your security deposit + interest at the end of an apartment rental)

great job,I just joined, I am a smart blogger

The goal of the formula that’s included here is to prevent a DAO from overdrawing the treasury for the reasons that you cite. We felt that in a smart contract world, 99.999% safe or a massively positive expected value investment doesn’t even cut it.

So it sounds like that formula mimics your implementation, but it calculates the “earned revenue” (which can be withdrawn) in aggregate rather than on a per token basis. This was important for the Geo Web because iterating through potentially millions of parcels would be computationally/cost prohibitive.

That said, we didn’t end up implementing this and instead went with non-refundable deposits. On transfers of land/tokens, the purchaser must reimburse the previous licensor for their outstanding network fee balance. The purchaser essentially inherits the fee balance (which they can add to at any time).

Quoting the important part of that post for easier reference and in case (centralized :smirk:) Substack goes away:

The new part is calculating earned taxes (aggregate funds that can be collected by the Geo Web org* from the contract) and a required reserves (unearned/prepaid taxes that must remain locked for potential refunds):

  • Required Reserve(T1) = Reserve(T0) + New Taxes Paid - Taxes Returned - Sum of Self-Assessed Values(T0) * (Tax Rate * Duration(T1-T0))
  • The above assumes a universal tax rate, but could be modified to handle multiple tax rates. We’ll likely measure duration between transactions in seconds, so the tax rate used in the formula would be per second.
  • Total Contract Funds(T1) - Required Reserve(T1) = Funds Available to Withdraw(T1)

The required reserve formula is concurrently updated with each of our basic contract functions. Aggregate tax collection/withdraws are now a constant time complexity transaction (thereby saving the fate of the Geo Web and the Ethereum blockchain).


I should have read that Wk2 Update linked above more closely : ) Makes sense!

We’ve moved the overarching conversation around this to the RadicalxChange Github discussion board for more visibility and project-neutral considerations. We’re excited about the prospect of standards for PCO NFTs, but will also need to push forward on our unique implementation needs, so we’ll post Geo Web-specific discussion here still.

Based on group discussions my baseline thinking for which PCO values to store and which are implied have changed. Here’s a cross post from the RxC board that summarizes that change in thinking for me:

My attempt to summarize the challenge is finding the right balance between the user experience of partial common ownership, technical limitations/implications of smart contracts, and economic reasoning.

It’s currently a big lift to convince people to adopt this radical property rights system, so making it easy to understand, use, and manage should drive a lot of design decisions to start (without sacrificing the core principles). This challenge is most apparent in the question and implementation of, “How am I even supposed to price property under this new system?” Pricing is a complex often subjective question even in traditional property rights systems. For many it’s just an exercise in +/- from an existing market reference. So… what do we do without a good existing reference?

My initial reaction was to embrace bottom-up economic reasoning: have users set their desired tax/fee payment rate and calculate their self-assessed value accordingly ( Self Assessed Value * Tax Rate = Payment Rate ). There are two problems here. As Matt pointed out, most people aren’t used to thinking in discounted cash flow terms and may prefer to just set their price directly and more subjectively. The second is that if you key off the tax payment rate (both from a user entry perspective & by directly storing the payment rate in the smart contract) the implication is that a change in the tax rate would immediately, proportionally lower all self-assessed values and the total market value. That could be quite jarring. In non-smart-contract-intermediated markets, changes to a tax rate would be factored into self-assessed values over time. There would be downward pressure from a tax increase on value, but you would also assume that the tax rate increase is being driven by a desire to pay for useful public goods, services, etc. that increase market value. How those two forces net out is up to the market.

Given the above, I now lean toward embracing the subjectivity and complexity of all that goes into a self-assessed value in the design and implementation of a PCO smart contract. Because changes in a tax rate would have complex impact on the market’s value, we shouldn’t try to bake in too many hard-coded assumptions. There isn’t a perfect or certain answer, so it seems that defaulting to the self-assessed value staying constant rather than the payment rate (effectively one or the other needs to be stored in the smart contract and you don’t want to have to do mass updates) is the safer choice. Users can and should update their self-assessed values and implied payment rates, but they can do that over time, factoring in their personal perspective/information to come to a new equilibrium.

Cody and I discussed the technical implications and tradeoffs around this today in the context of (eventual) streaming payments, global/individual rates, grandfathering in rate changes, and continuous/fixed period auction implementations. The move to discrete auction periods has the biggest potential impact on the architecture, so we’re both taking time over the next few days to sketch out what that might look like before proceeding. More to come…

Been thinking a lot about periodic auctions, especially in the context of Entry & storage of self-assessed values/contribution rates and changing tax rates. Here are some thoughts:

Periodic vs Continuous

Although perhaps the “purest” form of PCO, there are issues and tradeoffs with a continuous auction.

  • People may be turned off if they can lose their property at any given time
  • Certain use cases would be devastated by their land being bought
    • Temporary events, ETHDenver being bought by someone else during the event

Exploring a periodic auction could solve some of these issues and make PCO more conservative. Essentially, the new requirement could be:

A licensee should have the opportunity to guarantee their control of a license for some reasonable amount of time

Possible approaches

Method 1: Fixed-time deposits

  • All land starts as unclaimed
  • Anyone can create a new license from unclaimed land
  • Upon creation, the license is put up for an open auction
    • The person who triggered the creation/claim does not automatically get the license
    • Each bidder can place a bid that contains
      • Self-assessed value
      • License Duration
    • License Duration has a max, say 1 year
    • A bidder must make a deposit equal to the fees owed for the entire period
      • Value * Tax Rate * License Duration
    • Whoever has the highest self-assessed value at the end is now the licensee, and their deposit is collected
    • Any losing bidders may claim their deposits back
  • The license is now claimed with the following being stored:
    • Self-assessed value
    • Tax Rate
    • Expiration
  • If the expiration has not been reached:
    • No purchases are allowed
    • Licensee cannot make additional payments
    • Licensee cannot change value
    • Deposit cannot be refunded
    • Bids can be placed for next period
  • Once expiration is reached, the license is put up for auction again
    • Current licensee must submit another bid, like any other bidder
    • The new licensee must pay the previous licensee their self-assessed value from the previous auction
    • The Tax Rate may have been updated since the last auction, and would be reflected in this new period

This is a simple approach that allows a licensee to guarantee control of a license for some period up to the max License Duration, as long as they pay all the fees up front.

A major issue with this approach is the working capital requirement. Not only is a potentially large amount of working capital needed to bid, but the people with a larger working capital would have a major advantage over those with a small working capital.

Here is an example. Say there are two potential licensees (Alice and Bob) who both want a license for a year and who both value the license at $1000. The tax rate is 10%, thus the deposit required up front to purchase the license is $100.

Alice has $100 of working capital, but Bob only has $10 of working capital.

In PCO theory, Alice and Bob should be economically equal. In practice, Alice has an advantage because of the extra working capital. Bob, in this case, would either need to bid a higher self-assessed value or a smaller license duration.

A potential new requirement could be:

The current owner should be who values it the most for that period of time, not who has the most working capital.

This is not only an issue for this approach, but for our current design as well.

Method 2: Flow-based payments

Here is another method that could eliminate the working capital issue (or reduce it to be negligible).

Same as above, except:

  • During an auction
    • A bid contains
      • Self-assessed value
      • License duration is a constant for all bids
    • Instead of making a deposit, the bidder creates a Superfluid flow of the rate:
      • Value * Tax Rate
  • The license is now claimed with the following being stored:
    • Self-assessed value
    • Tax Rate
    • Expiration (constant based on License duration)
  • If the expiration has not been reached:
    • No purchases are allowed
    • Bids can be placed for next period
    • Licensee makes periodic deposits into the Superfluid Flow
    • A new auction is triggered if the licensee:
      • Closes the flow
      • Updates the value of the flow
      • Fails to pay/fund the flow
    • If a flow is closed or fails, the amount the new bidder must pay the current licensee is no more than the new licensee’s self-assessed value
      • Example: Current value is $100, flow fails, winning bid is $90. The bidder only pays $90 to the previous licensee, and not the full $100
  • Once expiration is reached, the license is put up for auction again
    • Current licensee does not need to do anything if they do not want to change their self-assessed value (flow stays open)
    • If the auction winner is a new licensee, the current licensee is paid their self-assessed value and their flow is closed

This approach allows the licensee to pay for their fees throughout the period, only requiring a 4 hour deposit in the Superfluid protocol. Any failure or change to the flow would trigger an auction to allow others to bid again.

The license duration would need to be constant, since there is no deposit that can be used to “outbid” others, thus eliminating the race to who has the highest working capital as described above.

Method 3: Refundable deposits

This approach also uses deposits, but allows for a licensee to not need to come back every period unless someone outbids them.

Same as method 1, except:

  • License Duration is a constant, say 1 month
  • A deposit can be greater than 1 month of fees
  • If the current licensee still has a deposit to cover 1 additional month and nobody else outbids them, they keep the license without needing to submit another bid
    • Max Expiration is stored instead of Expiration that is calculated from the deposit amount
    • Start Date is also stored
    • Expiration is calculated as the smaller of:
      • Start Date + (License Duration * (((Now - Start Date) % License Duration) + 1))
      • Max Expiration
  • If the current licensee is outbid during a period, they lose the license and may get their remaining deposit refunded
    • Refunds are calculate using a method described here

Supporting Multiple Payment Methods

The approaches above are very similar, but just differ in how the fees are paid. With our approach to modularity and reversible decisions, choosing a specific payment method (especially a niche protocol like Superfluid) is almost certain to be the wrong decision. So, is there a way we can support both payment methods and/or allow for switching between them?

Starting with the auction, the bids for both approaches are almost the same. Both contain:

  • Self-assessed value
  • License duration

Therefore, bids from both approaches can actually be used against one another and are interoperable. This means some bidders can be using flows while others are using deposits, all without needing to know which method the current licensee is using.

One catch is the max license duration used in the deposit method needs to be equal to the constant license duration used in the flow method. It would not be fair for users using the flow method to be “outbid” by a bidder using the deposit method with a bigger duration.

One contract can track the self-assessed value and expiration of licenses, without collecting payments. Two different contracts can be used to collect payments that have the necessary permission to transfer the license.

Bidding process

Adding more details for the bidding process.

In both methods, a bid consists of:

  • Self-assessed value
  • License duration (constant)

A bid can be placed at any time, but must include a deposit equal to the current licensee’s self-assessed value.

Once the open auction period is over, the winning bidder must send another transaction that:

  • Makes a deposit for taxes or opens a flow
  • Sends bid deposit to current licensee for claiming
  • Closes/cleans up the current licensee’s flow
  • Transfers the license to the new licensee

There could also be a commit-reveal model, where the initial bid has the bid amount hidden, only to be revealed on the second transaction. There would be the following bidding stages:

  1. Bidding
    • Anyone may submit a blind bid + deposit for paying current owner
    • Bid is a hash of their desired self-assessed value and a random number
  2. Reveal
    • New bids are closed
    • Anyone who placed a bid in stage 1 can now reveal by sending the unhashed message to be verified
    • If no bids were placed OR no bids are revealed, the current owner maintains ownership and the license moves back to stage 1 for the next period
  3. Claim
    • The highest bidder that revealed in stage 2 may now “claim” their bid by making another deposit for fees or opening a flow
    • This is the official point where the bidder is now the owner and the license moves back into stage 1
    • Anyone who submitted a bid in stage 1 (even if they did not reveal) may receive their deposit back
    • The previous owner may collect the deposit from the highest bidder
    • If the highest bidder fails to claim the license, their bid is invalidated and the license is put back into stage 2
      • Next highest bid can claim in stage 3, with their deposit now going to the previous bidder who failed to claim
      • This is as if the bidder bought the license and immediately failed to make payments. They would only receive what the next highest bidder is willing to pay, and not the full self-assessed value, just like if a normal licensee fails to make payments

If the current owner’s deposit or flow runs out AND nobody submits or reveals a bid, the license is burned and the land is made available for other claims.

Here is my attempt at diagraming this in a state diagram:


And the version without commit-reveal:



In both approaches, one limitation is for someone who wants to control a license for a specific period of time (like for an event), they will most likely need to bid for the license at the start of the period that contains the dates they are interested in. This is most likely much earlier than the actual date they would like to start owning it. This could be mitigated by having a shorter License duration. A limit of say, one month, would give a bidder the opportunity to bid for their interested period no more than one month in advance, limiting the unnecessary fees they have to pay.

Open Questions

  • Are modifications to land parcels allowed at any time?
  • Appropriate value for License duration
    • Needs to be long enough to protect owner, short enough to allow for events and other use cases
    • 1 month frequency is the latest proposed
  • Different tax rates and license durations for different “zones”?
    • Perhaps in the future it makes sense for certain parcels to have different license duration limits or tax rates based on some other factors
    • Sort of similar to zoning of physical land (commercial, industrial, residential)
  • Are transfers allowed when using Flows?
    • Transferring a license may not be allowed if the payment is made via a Flow
    • Does the new owner need to open another flow? Does the original owner keep the Flow open?
  • Failed streams and a dutch auction
    • Should the licensee with the failed stream receive an amount proportionally to how long they held it? If they only had it for one day, should they receive 1/30th of their self-assessed value?
1 Like

Awesome stuff @codynhat! We’ve chatted directly on earlier versions of this post and there’s quite a lot here to pull together, so I’ll try to keep this response short-ish. Here are my high-level notes and questions:

  • I definitely lean toward methods 2 and/or 3. In my mind there are two guiding business requirements for the implementation of periodic auctions:
    1. License Duration needs to be less than a year to allow the market dynamics to work on a reasonable timeframe (a year at this stage might as well be a decade), and it shouldn’t unduly favor those with more working capital. 30 days/1month seems right, but I’m open to arguments for longer/shorter.
    2. The current licensee should not be forced to come back and take explicit action to roll over their license under a no-change scenario (no tax change, no bidder, stream/deposit not depleted)
  • Is it accurate to say that the green nodes represent user-triggered transactions in the diagrams?
    • If so should there be one added for “liquidation” on the insolvent/no bids branches?
  • The notation and equations for the date evaluations are a little fuzzy for me. I think I know what you’re aiming for in each one, but I can’t map them cleanly to what’s there. Might need to add further definitions or I just need to brush up on developer notation.
  • The deposit obfuscation mechanisms in the commit-reveal scheme described in the soliditylang overview aren’t 100% clear to me yet. I’ll continue to reread and see if I can fully absorb it, but my general response is that it is appealing as long as we can design the extra transaction UX and education so that it doesn’t become overly burdensome or technically complex for now.
    • Is this something that could be considered “post launch” without too much rework or a migration?
  • Under a periodic auction system, I think it is appropriate for our Dutch auction mechanism for expired parcels to go away. We should either utilize the already established License Duration as the auction period or trigger (not with a transaction, but with if/then logic) a shorter, fixed-length one. I lean toward the latter, so we don’t have variability between 30 day and 1 day/second liquidation auctions.
    • We need to work out details of how liquidation auction proceeds are determined and where they go, but I lean toward not punishing the former licensee based on when in the license period their parcel expired (too penal for a parcel that happens to expire on the 1st rather than the 29th day of the previous period). As long as there’s good UX around the liquidation auction (sufficient time for bids & making clear to the bidders that they can bid below the previous self-assessed value), the market determining the amount the expired licensor received seems fair and would check be a check on abuse.
  • If we chose to store a parcel-level license fee rate, then a change to the global fee rate inherently requires a mass update or individual parcel updates bundled with other routine transactions. This would mean we’d grandfather in the rate change or set a deadline for licensors to take explicit action.

We are forking off the conversation around periodic auctions here: