We are exploring moving the Geo Web land market from continuous to periodic auctions (i.e. parcel transfers happen during specified, regular windows). This top post will contain a WIP specification that we will edit as needed to hone in on our final design while the replies will consist of our chronological discussion of the design thinking.
Draft Spec (Refundable Deposits)
Last Update: @graven, 2021-12-07
Set License Duration to 30 days (2,592,000s)
This will create a rolling 30 day periodic auction window for each individual parcel
All land starts as unclaimed
Anyone can create a new license from unclaimed land via the initial auction or ongoing claims.
A claim transaction should include the following actions:
Mint a license and set the minting address as the licensor
Set a Self-Assessed Value (stored value)
Set a parcel-level License Fee Rate based on the global rate(s) (stored value)
Stored as a per second rate (not yet multiplied by the Self-Assessed Value)
NOTE: Need to explore designs around this to limit parcel level updates on rate changes
Accept a License Fee Deposit payment (stored value)
Must be >= 30 days of license fees (commit for 1 period)
Must be <= 1 year of license fees (limits the length of time a parcel is “grandfathered” into a License Fee Rate change)
Set a Start Date for the license
Set a Update Date
A parcel’s next auction opening is calculated as the smaller of:
Update Date + (License Fee Deposit / (Self-Assessed Value * License Fee Rate)
I’ve been thinking of this as the license starting its life with an auction. Anyone can form a parcel and put it up for auction, but there is some period where anyone else may submit a bid as well. This would replace the “fair-launch auction” idea.
Otherwise, we would need a fair-launch mechanism in addition to the periodic auctions? I’m thinking that the fair launch can just be auction period 0 instead of design a separate auction mechanism.
I think we should answer this question first. Having a commit-reveal significantly changes steps 7-10. IMO, a blind auction is very important and we should have it at launch. There are too many unknowns in the economics around MEV and game theory that could have unintended behavior.
Technically, this is fairly straightforward. A hash of the self-assessed value and some secret can be submitted as a bit. This can later be revealed by the user “revealing” the secret. Traditionally, a big issue is where to store the secret. If the user loses it, they won’t be able to reveal their bid. We should be setup nicely to deal with this though. We can store the secret as an encrypted record in the user’s IDX. As long as they have access to their wallet and the record is pinned, they can easily recover their secret.
The one nice thing about the Dutch auction that this would miss is the aligning the opportunity to define the shape of a parcel with the bidder that values “some space” the highest. It might not be that big of a deal, but there would be a race to start auctions according to the shape(s) that you want. Someone might need to win two or more auctions to get the full space they value. Not sure if they’d end up having to price the parts in the auction less or more than the desired whole.
Sounds good. I can make updates tomorrow to reflect this (amongst other changes).
One bit of clarification:
Each bidder must reveal their own bid, right? There’s no way to do a batch reveal of some kind?
The challenge will be getting bids all revealed in a timely manner so the highest (revealed) bid can be processed as the winner. We might need to consider closing bidding and starting this process before the end of the License Period, so that a serial process doesn’t drag too long into the next period.
Do we need to trigger an auction for a claim post-Dutch auction and/or post-no-bid auction? As long as we have a sufficient initial auction period on expired parcels, then it feels like it should be fair game at that point, and we shouldn’t slow down a prospective licensor that is ready to go.
I don’t think another auction is needed post-Dutch fair launch auction. Does there even need to be a separate auction for expired licenses?
If there are no bids when a license expires, and the current licensee ran out of their deposit, this license could be free to claim by anyone. There was plenty of time for people to see the license was going to expire and to submit bids for the next period.
Yeah definitely agreed that post-Dutch auction, new parcels should just be open for claims.
For expired parcels, I think there are two conditions that we’d need to enforce then it would be reasonable to assume that everyone got a fair shot at the claim:
Don’t allow current licensors to pull their deposit or change the self-assessed value in such a way that results in an expiration date <1 month (or some minimum length) into the future. This would prevent surprise/super short auctions which look a lot more like FCFS.
Need to allow bids to be placed at less than the current self-assessed value then logic at bid reveal/execution determines if it’s valid (i.e. expired parcels can be purchased for less than the self-assessed value while normal periodic auctions wouldn’t allow that).
Those seem like reasonable requirements to me and would simplify things quite a bit.
We could add restrictions for the refundable deposit case, but not if using Superfluid flows (or potentially other methods too). I think we need to be flexible enough to handle the case where a parcel can suddenly become available. Maybe the license shouldn’t jump directly to the Reveal stage but have some period where it is still in Bid but expired? See this diagram:
Under commit-reveal, the bid amount is not known at the time of the commit, so bids under the current self-assessed value could always be submitted. This could turn into a winning bid in this case of a license expiring early, or if a license expires without the licensee having another bid or autobid.
Cody and I had a chat last night to talk through the various scenarios and the appropriate way to treat them. There are several scenarios where the answers aren’t yet clear:
How to treat winning, revealed bids that are not executed during the specified claim period. We’re leaning toward treating it like a parcel that was transferred, but immediately expired and would be up for auction. The transaction to pay or withdraw the payment owed to the previous licensor would still need to be processed. We also talked through different scenarios where the next highest bidder would get a chance to claim the land, but that could hypothetically be the start of a never-ending series of unclaimed bids.
How to handle the auction/bidding for a parcel that suddenly becomes expired because the licensor ended a flow or withdrew their license fee deposits. We could set minimums on the license fee deposit, but the issue would still be there for flows. In a sudden expiration scenario, we would want to any allow outstanding bidders the chance to factor in this new information (the parcel is expired and could be purchased for less than the previous self-assessed value). But we also don’t want to create incentive or attack vectors for a current licensor to intentionally trigger that action in the face of outstanding bids. What phase the license is in during the auction process (bidding, reveal, claim) might require different treatment.
A big question to consider is the effect of Sybil attacks on the blind bidding process especially if a bidder isn’t required to reveal their bid. Would someone with enough available capital be able to enter many bids of escalating values only to reveal the lowest one necessary to maintain the winning bid in the auction?
Lots of challenges yet to think through. We’ll keep iterating through possible periodic auction designs, but it’s also possible that other continuous designs with some protections built in for the current licensor would achieve our business requirements (lower uncertainty to help a wider audience get comfortable with the system & give some protection to unexpected transfers undermining some use cases/investment).
Penalty calculation edge case with global rate change
Current design has a fixed penalty fee as a % of the difference in new and old self-assessed values. When the global contribution rate is changed, there is a case where the new SAV may actually be less than the old (but the contribution rate is higher).
One solution to this is to have the penalty be a % of the difference in the annual contribution rate. Example:
Current: 10 ETH vs 9 ETH @ 10% → 0.1 ETH
New: 10 ETH vs 9 ETH @ 10% fee @ 50% penalty → 0.05 ETH
Dutch auction and flow termination
There can only be one flow from a wallet to the CollectorSuperApp. This means there will be one flow for all parcels owned by a wallet. If this flow is closed, all parcels owned by that wallet would be put in a Dutch auction.
This may seem extreme, but it is mitigated by:
Dutch auction slowly just declining the value instead of instantly being 0
User still being able to reject bids that come in during the Dutch auction
There is a similar issue, not when a flow is closed but when a flow rate is lowered to be less than the sum of all the wallet’s contribution rates. In this case, we have two options:
Awesome work @codynhat! I’m still working through internalizing the full specs, but I’ll drop in my thoughts on the open questions below:
Good eye the edge case. I like your solution for its simplicity in implementation and our ability to explain it simply (i.e. in your example a 50% penalty is “a penalty of 6 months in back fees”).
Besides this, I have been thinking about the goals of this penalty since we last talked about it. I’ve been considering the impact of calculating the penalty based on solely the new SAV (without subtracting off the previous one). This would “raise the stakes” for high priced parcels on a relative basis for small increases in value. You could justify this as helpful in preventing whales from just accepting penalties as the cost of doing business and systematically skewing their SAVs lower. The global penalty rate would still need to be right-sized, so penalties (especially on low value parcels) aren’t too onerous to make matching impractical.
Dutch auctions & flows
It doesn’t feel right to me for the (former) licensor to be able to reject bids in a Dutch auction. Are you saying that we could build that in or that it would be like that? I’m pretty comfortable with a portfolio going into Dutch auction if a stream runs dry as long as…
… We are able to prevent a user from lowering their flow below their required rate. This seems like it would only happen by mistake or if a person doesn’t fully understand the consequences of making the change. If a deposit runs out by neglect, it’s fair to put things into auction (there have to be some consequences for the market to function). Putting a potentially big portfolio into auction instantaneously because a fat finger feels too dramatic though.
Ok sounds good. We could do it based on the new SAV too. This would incentivize larger value parcels to more accurately set their value? It makes sense for lower value parcels to be penalized less, since you could argue they are more difficult to self-assess. This is sort of a “progressive” penalty?
I was assuming we would support that. But it isn’t required. I will update the proposals to have a Dutch auction bid immediately transfer a parcel.
We can also revert and prevent someone from lowering their flow too much. I believe this is supported in Superfluid. What is not supported is reverting when a flow is closed. Whenever a flow is closed, the portfolio will have to be put up for Dutch auction.
I think using the new SAV makes more sense than the old one in the “gross method” setup. But yeah it’s a more progressive of a penalty when you don’t net out the old SAV. Ex. A 1ETH parcel receives a 2ETH bid vs. 100ETH parcel receives a 101ETH bid. Under the net method, they pay the same penalty to match. Under the gross method, the expensive parcel is paying 50.5x the penalty for the same absolute underpricing amount. There’s good and bad to that…
Dutch auctions & flows
Sounds good. Let’s do what we can to prevent fat finger mistakes, but let closed flows (intentionally or by neglect) have their consequences.
With work progressing on our chosen owner forgiving auction setup (bid accept or reject+penalty), @codynhat and I revisited the mechanics and incentives of our system in a conversation today. The main point we explored were the ways that a bidder could potentially game the auction to artificially decrease the chances of a current licensor matching their bid and/or extracting profit.
As currently constructed, a bidder collateralizes their bid in an amount equal to the outstanding SAV. They are able to set a new, higher SAV at the same time (which doesn’t require any additional collateral). To reject a bid, the current licensor must pay a % penalty based on the previous SAV (or potentially other calcs) AND raise their SAV to the new, higher one set by the bidder.
In this setup, there is limited cost to a prospective bidder bluffing an artificially high SAV that deters a licensor from matching the bid (after a bid is accepted/not matched, the winning bidder can instantly lower their SAV). If this were to happen, the market could (should?) find the fair valuation through multiple rounds of over bidding & lowering the SAV, but this is inefficient (especially with 7 or 14 day bid matching periods) and could allow predatory bidders to extract profit (by reselling the asset to the previous licensor at a price greater than the old SAV, but lower than the bluffed SAV which wasn’t matched).
Based on this, we discussed a spectrum of 4 options to associate cost to the SAV of a bid placed to encourage honesty:
Collateral = Old SAV: This is the current setup where a bidder can set their new SAV without any constraints or additional collateral. This collateral is paid to the previous licensor if a bid is accepted.
Collateral = New SAV (with immediate release): In this setup, a bidder would incur the short-term cost of capital required to fully collateralize their bid. The value of the old SAV would be paid to the previous licensor and the remainder would be returned to the bidder upon bid acceptance.
Collateral = New SAV (with a lock-up period): Like in #2, the previous licensor gets paid when a bid is accepted, but in this setup the additional collateral up to the new SAV would be locked for some defined length of time.
Pay the full amount of the New SAV: In this setup, the bidder is required to pay for the full value of their bid. The previous licensor would be paid their old SAV and the excess value would be paid into the treasury. This would be the most extreme version and effectively eliminate the “alpha” of finding an undervalued asset.
I currently lean toward #3 first and then #2. The optimal answer usually is found somewhere between the extremes. I’m hoping to connect with Anthony Zhang sometime next week for a general intro/talk, so this would be a good discussion question to pose to him.