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

KIP-0013: Poly Fungible V2, manifests and token policies #20

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions kip-0013/kip-0013.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
KIP: "0013"
Title: poly-fungible-v2
Author: Stuart Popejoy [email protected], Hee Kyun [email protected]
Status: Draft
Type: Standard
Category: Pact
Created: 2021-02-02
---

## Abstract

Improve the Pact multi-token [poly-fungible-v1](https://github.com/kadena-io/KIPs/blob/master/kuip-0011/kip-0011.md) standard to encompass

- a) token sales,
- b) Haber Content Integrity manifests
- c) pluggable token policies.

Intended to support Kadena "Marmalade" NFT decentralized infrastructure, these allow enforceable sale standards that encompass royalties, sales in any coin, better NFT integrity and identification, and more.

## Motivation

While poly-fungibles/ERC-1155's can behave like "normal" coins, NFTs aren't tokens  -  the whole point of
"non-fungibility" is to indicate that this item can't be traded for another. In a coin-like token,
transfer is the main operation: money changes hands. For an NFT however, transferring it from one owner to another
leaves out a crucial step: the sale of the NFT.

The problem with the ERC transfer-only model for NFTs appears whenever you want to do something beyond simply buying the
NFT from the current owner with no strings attached. For instance, an oft-touted feature of many NFTs is their ability
to pay a royalty to the original creator every time the artifact changes hands.

One would think this means the blockchain makes it impossible to sell or transfer the NFT without collecting the
royalty. Unfortunately, it doesn't work this way with current Ethereum royalty standards like ERC-2981, supported by
exchanges like OpenSea or Nifty. Under ERC-2981, the NFT ledger exposes a function that takes a price and computes a
royalty and receiver for a given token. The enforcement is entirely handled by the exchange, such that they essentially
pinky-swear that whenever they make a sale, they will always call this function, and distribute funds accordingly,
before calling transfer to hand the NFT to the buyer.

### Pacts for sales

Kadena's smart contract language Pact has the critical missing feature: "pacts", which are multi-step processes defined
in the smart contract. With pacts, we can finally see what an enforceable NFT marketplace standard looks like. The first
step is **offer**, in which a seller lists an NFT for sale. This puts the NFT into a trustless escrow that can only be
released by later steps of the pact. The second step is **buy**, where a buyer executes some offsetting payment, and the
escrowed pact is transferred to the buyer. If the buyer never shows up, after a timeout the seller can "roll back" the
pact and **withdraw** the sale, transferring the NFT back to the seller from the escrow account.

### Token policies

The sale pact is the critical piece of logic that powers mintable marketplaces, since it introduces a fully autonomous
and enforceable way to offer tokens for sale within the standard. However, the token policy handles critical aspects of
the sale, such as how does money change hands? How might a royalty be implemented? And also, doesn't transfer still
undermine everything?

Token policies don't just govern sales, but transfer, minting, and burning as well. This is necessary to make a truly
enforceable token policy:

- Creation. The token policy is invoked when a token is created (this is distinct from minting, which actually
establishes ownership of the NFT). This is where something like a royalty rate or other "permanent" data would be
captured.

- Minting. One thing about ERC-1155 (and poly-fungible-v1 too) is the lack of a way to lock down issuance. With the
minting policy, a token can declare itself to be a true 1-of-1, or limited series, or a fully fungible coin.

- Burning. Burning is already a head-scratcher for NFTs, but can obviously make sense for fungible coins. Burn policies
allow prevention of burns in 1-of-1 and limited-series NFTs, as well as other rules a creator may desire.

- Transfer. Transfer can finally be tamed with the transfer policy! For most NFTs it gets banned altogether, but it also
serves other use cases like transfer restrictions, minimum or maximum order sizes, etc.

- Sale. Sale policies have separate operations for the offer and buy steps of the sale pact. Offer is where you might
quote a price, and buy is where an offsetting transaction can be executed.

### Manifests

Haber Content Manifests replace opaque and unverifiable NFT URIs with cryptographically verifiable on-chain data,
employing elements of Stuart Haber's Content Integrity designs. This can be anything from a simple Data URI or DID
(Decentralized Identifier) to any structured data, including image or document data on-chain.

## Rationale/Discussion Items

### Trustless escrow

Pact's trustless escrow functionality is considered critical to make an enforceable sale standard. The token policy
works with the "offer" and "buy" steps to customize requirements for a given marketplace.

### Withdraw timeouts

Currently withdraws are not customizable and only offer a block timeout.

### DIDs and Token Identifiers

Manifests bear a content hash that can stand in as all or part of a verifiable ID for the NFT. A separate
standard will discuss an _address protocol_ (KIP-0012) for guaranteeing a token ID matches the manifest. Open
issues include the fact that the policy is not currently captured, perhaps an ID can identify the policy
as well.

## Backwards Compatibility

### poly-fungible-v1

Manifests in `create-token` and the `manifest` accessor break compatibility with `poly-fungible-v1`.

## Specification

- Interface: [poly-fungible-v2.pact](https://github.com/kadena-io/marmalade/blob/marmalade-rc1/pact/kip/poly-fungible-v2.pact)
- Interface: [token-policy-v1.pact](https://github.com/kadena-io/marmalade/blob/marmalade-rc1/pact/kip/token-policy-v1.pact)
- Implementation: [manifest.pact](https://github.com/kadena-io/marmalade/blob/marmalade-rc1/pact/kip/manifest.pact)

## Reference Implementation

- Marmalade RC1: [ledger.pact](https://github.com/kadena-io/marmalade/blob/marmalade-rc1/pact/ledger.pact)

## References

- EIP-1155: <https://eips.ethereum.org/EIPS/eip-1155>