Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What token interface should we use? #51

Closed
ryscheng opened this issue Dec 14, 2022 · 8 comments
Closed

What token interface should we use? #51

ryscheng opened this issue Dec 14, 2022 · 8 comments
Assignees
Labels
category:onchain Smart contracts p0:urgent Must address immediately

Comments

@ryscheng
Copy link
Member

ryscheng commented Dec 14, 2022

What we already agree upon:

  • For any particular hypercert, partial/fractional ownership of that hypercert is fungible and interchangeable. If a hypercert represents (A v B), and Alice and Bob own 50%-50%, there is no world where Alice's 50% is worth more than Bob's
  • For our initial MVP, we will try to store most claim data off-chain. In future contract upgrades, we may open up the option to store more data on-chain (e.g. for automatic collision detection), but for now we cannot assume to have access to any claim data on-chain.

What are the options?

  • 3525 semi-fungible token: where the slotID is used to represent a hypercert and a tokenID is an NFT that represents a particular user's fractional share. If tokenID1 and tokenID2 are each 50% ownership of a hypercert, they should share the same slotID. We would need to store additional data (i.e. units that represent how large of a share this represents)
  • 1155 semi-fungible token: same as above, except the interface does not support an explicit "slotID" that we can use to group NFTs as fractions of the same hypercert. Thus, we encode the slotID/hypercertID/claimID as the upper 128 bits of a tokenID and use only the lower 128 bits to represent which fractional share we are talking about. Thus, a 256-bit tokenID still represents an NFT of a user's fractional share of a hypercert.
  • 1155 fungible tokens: We use the tokenID to represent which hypercert we are talking about. Each tokenID has a fungible total supply and a table of token balances for each account.

Considerations:

  • While we can easily upgrade contracts, changing the interface can be quite difficult. This decision also affects how we represent the underlying data structures
  • The way these tokens look will be different on OpenSea. For the semi-fungible case, we can create a unique image for each fractional share of a hypercert, because it's a unique NFT. For the fungible case, we can create an image for the hypercert, but a user's share will be represented by a "x 100" chip in the top left corner of the image if the user has 100 tokens. This is a built-in behavior by OpenSea.
  • Do we want to be compliant with multiple different interfaces simultaneously to work in different marketplaces (e.g. both OpenSea + Solv?)
  • What happens when we split/merge on claim data? In each of these options, because claim data is stored off-chain, we need to burn/freeze the input tokens and mint a new hypercert that links to what was frozen.
  • What happens when we split/merge on value? For the fungible case, we are adjusting token balances. For the semi-fungible case, we'll have to create new NFTs.

For reference:

@ryscheng ryscheng self-assigned this Dec 14, 2022
@ryscheng ryscheng added category:onchain Smart contracts p0:urgent Must address immediately team:question labels Dec 14, 2022
@ryscheng ryscheng added this to the Gitcoin Launch milestone Dec 14, 2022
@holkexyz
Copy link
Member

Strong opinion: Let's not consider compliance with Solv for making this decision. If it'll work on OpenSea that's great.

Questions:

  • ERC20 was mentioned in a chat yesterday, but it isn't an option? (I don't want to bring it up, but if it is an option, let's put it all on the table. I assume it isn't mentioned as we wouldn't have any representation of the certificate associated with it?)
  • Why do we need to burn and mint new tokens if we split/merge on value in the 3525 case? I assume in the 1155semi-fungible case, we need to burn and mint new tokens because it changes the tokenID, right? In the 3525 case it would be an adjustment of the units only (I assumed that is the benefit of 3525)

@bitbeckers
Copy link
Contributor

bitbeckers commented Dec 14, 2022

Below my view on some of the points above. Additionaly, I want to underline the difference between the hypercerts interface (close to an EIP) where we describe required methods and effects and the hypercert implementation we're currently developing. Because we want to be able to meet specific needs and operate cross chain there's will not be a single hypercert contract but hypercert compliant contracts. The weight is on the SDK, example app and other tooling to work with metadata and other state changes.

My biggest arguments in favor of SFT instead of FTs is the experience of NFTs and the ecosystem and understanding around it. Marketplaces, perception (owning a NFT), uniqueness (owning 1/2 feels better than 9_000_00 of 18_000_000). I understand these are subjective.

Marketplace UX

The way these tokens look will be different on OpenSea. For the semi-fungible case, we can create a unique image for each fractional share of a hypercert, because it's a unique NFT. For the fungible case, we can create an image for the hypercert, but a user's share will be represented by a "x 100" chip in the top left corner of the image if the
user has 100 tokens. This is a built-in behavior by OpenSea.

We assume to build a SDK that manages the state of the data stored on IPFS and to keep the token URI up to date. This would also include the image generated. So the URI for the tokenID points to a CID referencing the full metadata set.

Example of schemas in SDK

Does the x100 chip suffice?

Since the amount of units minted is arbitrary, x100 does not mean anything. This could require the user to do some mental math to understand how much of the impact they are funding.

For example the x100 is almost insignificant if 1 * 10^18 units were minted. Therefore you could argue that you want the image to represent the percentage represented by a fractional token.

Can we store custom SVGs per fraction?

Yes. This would also enable us to represent whether a fraction has been donated and the proportion of the claim it represents. But, a malicious or misinformed actor could upload an incorrect image and the marketplace would not surface this information.

For example, I upload an image claiming "99%" owned, while it's "9.9%".

Can we generate dynamic SVGs on-chain?

An option to do this dynamically, would be to render the metadata on-chain, including the SVG, but with the actual claim data, the CID reference, stored behind an "external_url" field as URL. For an example see the OpenSea doc.. Also, Uniswap V3 positions are a very good example of -the power of- dynamic SVGs.

However, this could become messy because if, for example, an IPFS gateway is down the external data becomes unaccessible. Taking inspiration from Grants Protocol, we can also create a metadata pointer describing protocol + identifier. When a user or marketplace want to read the metadata, we query a gateway endpoint for the protocol and attach the identifier. Migrating gateways would only require a single point to be updated. Rendering the up to data URL would all happen on-chain.

For example:

Metadata Pointer:
Protocol "ipfs" => resolves to "https://gateway.ipfs.io/ipfs/"   
Identifier "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"   

URI:
"ipfs" => resolves to "https://gateway.ipfs.io/ipfs/";
"https://gateway.ipfs.io/ipfs/" +  "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"   

ERC20

A few reasons against ERC20, especially considering ERC1155:

  • For ERC20s we would need to have either one contract per hypercert (one token per contract) or it would be the fungible tokens at a ERC1155 (supply > 1). Could be done with a factory, but costly.
  • There's no metadata defined or even expected
  • ERC20 marketplaces are DEX-es, not OpenSea or other NFT marketplaces

Split/merge

What happens when we split/merge on claim data?

See this ticket for more details on the -currently- proposed solution. Basically, if a fraction get's split in 2 on impact (or other scopes) it creates 2 new claims, each representing a subset of the original token and both referencing the original token.

What happens when we split/merge on value?

For the fungible case, we are adjusting token balances. For the semi-fungible case, we'll have to create new NFTs.

This is true for the 1155 implementation. It does feel like there could be messy UX on marketplaces. In the case of SFTs, one can use an app to split 50% into 30% and 20% and use either the same app or OpenSea to auction 20%. Again, especially if it's represented in the image that can be powerful.

In the 3525 case it would be an adjustment of the units only (I assumed that is the
benefit of 3525)

No, if you merge the full value the empty tokens are burned. Otherwise you'd transfer value, not merge tokens. If you split a token, new tokens are minted and value is transfered from the original to the new one.

@ryscheng
Copy link
Member Author

Holke has a point that we might want to dynamically update the SVG depending on evaluations as well (e.g.a golden frame if there's a good evaluation from XYZ)

@bitbeckers
Copy link
Contributor

In that case you’d want dynamic SVGs right? Maybe even need them.

@ryscheng
Copy link
Member Author

yes I think you're right. Thank you for sharing your thoughts, seeing them in written form definitely helped make it more clear for me.

Long-term, I think there's a fundamental trade-off between focusing on user utility of an NFT (case for SFT) and supporting more efficient transfers for financial instruments (case for FT).
Talking to @ccerv1 and @holkeb I think we agree that user utility and dynamic SVGs are more important right now --- so SFT makes sense.

@bitbeckers, we also talked about expanding our 1155 implementation in the future to potentially support fungible tokens if we need to in the future, which is a nice option.

We also talked about just writing a Hypercerts interface and implementation, which we can also turn into an EIP in the future. For now, we can create a 1155 (or 3525) wrapper around it to make it compliant for OpenSea.

Anyway, long way of saying, I think we're in alignment, thanks everyone for sharing your thoughts. It's an important decision so glad we at the very least documented our current thinking

@davidad
Copy link

davidad commented Dec 16, 2022

I am late to the party here but I agree with what seems to be the current conclusion— semi-fungible with 1155 seems to me like the best tradeoff.

@ryscheng
Copy link
Member Author

Closing this for now, happy to re-open if we need to revisit

@ryscheng
Copy link
Member Author

ryscheng commented Jan 8, 2023

For reference, there's a section in the EIP-1155 spec for implementing "split IDs" like we do for semi-fungible tokens
https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:onchain Smart contracts p0:urgent Must address immediately
Projects
None yet
Development

No branches or pull requests

5 participants