- We’ve updated the “Motivation” section to clearly describe the document’s goal: Specifying a similar mechanic as World of Warcraft’s “soulbound items” like Ragnaros’ Thundefury: EIP-4973: Account-bound Tokens
Just for the record, I disagree that a “Soulbound Sword” makes sense as address bound. The sword is bound to a character usually, sometimes to an account, but the account can undergo credential changes, unlike an Ethereum address.
balanceOf
is now part of the interface and reference implementation: Add `function balanceOf(...)` by TimDaub · Pull Request #5172 · ethereum/EIPs · GitHub
We’re making progress with implementing mintWithPermission
and are getting ready to write up the change to the spec too. Here’s the latest implementation: ERC4973/ERC4973Permit.sol at 5e7d50ec62d9592f425c4cccd2fc3c3b8aca48c1 · rugpullindex/ERC4973 · GitHub
-
signature(hash(from, to, uri), from.pk)
allowsto
to keep the token off-chain and take the token on-chain withfrom
's permission - In a 2^256 big bitmap, we’re making sure that any combination of
hash(from, to, uri)
will only be minted once - EIP-1271 support is included so contracts can allow minting as
from
too - tokenIds are incremented internally so that we don’t have race conditions of two or more users redeeming at the same time
- signatures are now EIP-2098 compact representation compatible
feedback is welcome
Just for the record, I disagree that a “Soulbound Sword” makes sense as address bound. The sword is bound to a character usually, sometimes to an account, but the account can undergo credential changes, unlike an Ethereum address.
This statement is misinformation. An Ethereum account (e.g. a contract) can undergo credential changes, e.g. different EOAs can manage a contract’s functionality. It depends on the implementation of the contract but it is entirely possible.
Have we lost our path with this specification? I’m actively asking myself this question these days: Why? Because originally, I set up to define a token standard that is “ownership concept” neutral or non-skeuomorphic: And since we’re now defining consensual mintWithPermission
instead of bumping the document’s status to “Review.”
Here’s what I deem immediately useful to the Ethereum community today.
A token standard document that carries as little implicit notion of private property as possible - the goal being to innovate on different kinds of property, e.g., “Harberger Property,” [1,2,3] partial common ownership [4], and to, e.g., replicate the true nature of bits on the internet [5, 6].
It may not be entirely clear to many, and we probably haven’t done the best job at communicating: But it’s clear that if we had configurable property that isn’t implicitly biased towards, e.g., giving all possible rights to the “owner,” at least in the self-referential digital space many call “web3,” we could attack such interesting problems.
Buterin et al.'s “Decentralized Society” contributes to the Account-bound tokens specification, despite scope-creeping the entire field: It unbundles the concept of ownership as a bucket of interaction rights.
“4.7”, the “Plural Property” section brilliantly identifies the challenges we want to address [7]:
- web3 overemphasized the notion of “transferability” of property, making it impossible to represent simple and ubiquitous property contracts like an apartment lease.
- Traditionally, property rights are defined in Roman tradition as bundles of rights:
- rights to use property (“usus”)
- rights to consume and destroy (“abusus”)
- rights to profit (“fructus”)
- In the real world, someone rarely possesses the “full bucket” of ownership rights.
So to re-iterate on the introduction of this post: I’ve become unsure if we haven’t lost our path here. For E.g. the argument that ABTs discourage key rotation is blatantly false and misguided in the actual context. It’s because truly our intent isn’t to “bind” to accounts: But more to establish a new and unbiased relationship between on-chain property and their subjects (users).
Consider the tables and chairs in a bar. They’re owned by the bar: But then nobody really owns a chair in a bar. You get up (e.g. to the toilet) and then in some social contexts and depending who you are and what peers are with you in the bar - your chair is free when you come back or it isn’t.
This is the type of new ownership experience I’m talking about. E.g. making a differentiation between possessing, squatting, and owning. Using, profiting, transferring, lending, destroying, remixing, etc.
For that, my initial design goal was to strip EIP-721 of all implicit notions of transferability and private property. Yes, we could have used more proper terminology like: “function controllerOf” rather than e.g. “function ownerOf” - but to me, there has always been the question of backward compatibility.
E.g. If we end up creating an entirely original token standard in a vacuum, like EIP-5114 - will there be adoption? Having recently been exposed to the “worse is better” idea [8], I’m still of the opinion that “worse” and hence backward-compatible, is better.
Still, now that we’ve successfully implemented function mintWithPermission
in the reference implementation and since we’re now making normative statements about a user’s “abusus” rights (namely when it should be burnable), I’m wondering if we’re not getting overly biased again.
Here’s what I want for EIP-4973: I want to create the most minimal and backward compatible version of a token that carries as few implicit skeuomorphic ownership biases from our modern world as possible. I deliberately don’t want to replicate existing ownership experiences.
Then, and even though this may be to the detriment of some EIP editors that e.g. are asking for “censorship-resistant” tech (looking at you @MicahZoltu), I’d want to “finalize” EIP-4973 as a base token such that others can e.g. re-implement new and existing ownership experiences.
So how would we get there? E.g. I’d be happy to remove function burn
again. I’d also be happy to put a statement in saying that this standard shouldn’t be used to bind tokens non-separable to an account. And I wanna frame it where this standard becomes the bare minimum boilerplate standard for an on-chain property.
I hope that sounds reasonable to everyone! How do we get there?
References
- 1: Non-Skeuomorphic Harberger Properties may not be implementable as ERC721 NFTs
- 2: Harberger Taxes can be Crypto's Sustainable Business Model
- 3: What happened at Gitcoin's Schelling Point event?
- 4: https://partialcommonownership.com/
- 5: Built on Stolen Data
- 6: Posner, Eric A., and E. Glen Weyl. “Radical Markets.” Radical Markets. Princeton University Press, 2018.
- 7: Weyl, E. Glen, Puja Ohlhaver, and Vitalik Buterin. “Decentralized Society: Finding Web3’s Soul.” Available at SSRN 4105763 (2022).
- 8: Worse is better - Wikipedia
What was the motivation behind mintWithPermission
? Isn’t the goal already achieved by adding burn
into the standard?
I would say mintWithPermission
is too opinionated to be added in the specification, as it reduces the scope of application quite a bit.
I still feel like burn
should stay in the standard as a way to publicly react to a specific SBT, and I think it would enlarge the scope of applications, without making any unnecessary assumption.
I like mintWithPermission
.
Means that the receiver can decide to mint it or not. If it’s from someone they know or are expecting it then this works for that.
It’s stops being tarnished with sh*t ABT tokens that you don’t want to spend the time and expense to burn, so you leave it and people get the wrong impression.
Therefore, I think burn
is no longer necessary.
Agree that it can be a good way to use ABTs but I think it’s too opinionated to be put into the standard, imo it restrict use-cases for it quite a bit.
Entities can choose to implement the standard with mintWithPermission if they want to but ABT’s scope is way larger than that.
Btw, it’s not easy to decide where we draw the line between interface and implementation, but I feel like specific behavior like minWithPermission should be dealt with at impl. level
I suggest that we standardize mintWithPermission
outside of this standard (in another EIP). It can also be useful for any EIP-721 token. And generally, we probably also want another variant of mintWithPermission
where the from
mints for the to
(mintWithPermission
is implemented where to
needs permission from from
).
The tokens definitely do need to be transferrable, in case people want to rotate keys or if they want to move to a more effective system of organizing things.
But one should not be able to transfer tokens to a different human
One simple way to do it is to allow transfers only to accounts with the same label, where the label is a fully qualified name of the human.
In this case “Alice XYZ” will be able to transfer her tokens to another wallet with a label “Alice XYZ” but not to a wallet with a label "Bob 123’
That is easy to overcome.
I set the sub-domain, I transfer the NFT, then I reset the sub-domain.
I don’t think there is a way to enforce that limitation. So, the possibilities are either to allow transfers (maybe blocking approvals) or to disallow them.
It seems to me a solution similar to the attempts of forcing a royalty on ERC721, despite that the standard does not support it.
If I want to abuse that, how can someone block me from implementing a “mintWithPermission” function that actually does not require any permission?
Major changes are coming to ERC4973: We’re extending the Soulbound item capabilities of World of Warcraft. Namely, because you can “give” and “take” items to others.
- You can “take” an item from a dragon
- You can “give” an item to a friend
- You can “equip” an item, showing it to everyone in Ogrimar/Stormwind or you can choose to “unequip” it.
- I’ve rolled back the Attest/Revoke events. It’s now Transfer again.
I’ll take some time to adjust the standard’s document, but the new interface is actively being developed over in the reference implementations GitHub: Language develop standard towards Soulbound items · rugpullindex/ERC4973@27a62d1 · GitHub
In case you’re looking for a naive implementation of “Soulbound tokens” that non-separably binds an EIP-721 to an account, I recommend you check out EIP-5192 - Minimal Soulbound NFTs
Have been thinking more about the inclusion of balanceOf
. The original argument about it needing it to inform the reputation based on number of ABTs you have seems flawed.
For example, if you have 5 ABTs, with 5 different tokenURIs, it may not very useful to know that a user has 5 ABTs in total. It is perhaps rather more useful to know if a user has an ABT of a certain type of tokenURI
It is perhaps rather more useful to know if a user has an ABT of a certain type of tokenURI
I believe it was me that mentioned the use case for balanceOf
. I can imagine that doing the spec for this EIP is particularly difficult as it has to be loose enough to fit many use cases, and remain as minimal as possible.
You’re saying that tokenURI indicates a “certain type” but that I believe is implementation specific. For example, each student receives individual tokenURI’s that says they passed (with additional info like grade etc.) but they could be for the same qualification type. It could be that the ABT contract address represents a type (of qualification), or does it? There could be separate ABT token contracts for each school year, or departments etc. Again, implementation specific.
For a community giving the same type of ABT token to an address (the use case I mentioned earlier), balanceOf
would indicate strength of e.g. approval/trust given from the community; each tokenURI could point to text input of why a particular community member decided to give this ABT token. In this case, the ABT contract address could indicate a certain type. Still an implementation detail I feel that can work within the spec.
I know that the latest spec has removed Revoke
but I believe a rethink is necessary.
Hard to predict of course without running this in the wild but imagine a scenario that an ABT has built great reputation but was somehow duped by an outfit that then did something terrible, like a rugpull. Then anyone who had built up a good reputation/business from holding that ABT would then be affected unfairly.
A worse scenario could be that the community is unaware about the bad actor, since they still hold the ABT that continues to affirm them as a good actor, unknowingly, relationships would continue as normal.
I believe in these scenarios, the issuer should be able to recall the ABT from the bad actor, in order to save the ABT’s trust level and for it not to affect all others holding and the issuer of the token unduly.
I understand the argument that it can be used by the issuer for manipulation but any well functioning community would devalue that ABT token anyway.
So a rethink to introduce Revoke
again in some form, I believe is necessary, else it could seriously affect trust/adoption if the above type of scenarios happen often.
Hey, we just renamed Revoke to Transfer(owner, address(0), tokenId) in the reference implementation. It’s syntactically it’s different, semantically it is the same.
Updated EIP-4973 with the long-intended changes here: Adjust EIP-4973 interface to add `function give(...)` and `function take(...)` by TimDaub · Pull Request #5209 · ethereum/EIPs · GitHub
- Added a
function give
and afunction take
that both respectively allow minting a token consensually between two addresses using EIP-2098 and EIP-1271 (so can be used to proxy consent too) - Backtrack to
event Transfer
- Introduce the mental model of “equipping” and “unequipping” tokens as metaphor for “on-chain” vs “off-chain.” Hence, rename
function burn(...)
tofunction equip(...)
As there have been questions about how to generate the compact signature required to pass function give(...)
and function take(...)
and since specifying the code within the .md document, I’ve opted to create a JavaScript function using ethers that can generate the signature and also informs the structure of the inputs.
The resulting section “EIP-712 Typed Structured Data Hashing and EIP-2098 Compact Signature Creation” is more concise now and points to the .mjs files: EIP-4973: Account-bound Tokens