Skip to content

Commit

Permalink
Add cw1155 specification
Browse files Browse the repository at this point in the history
Design decisions:
- Fungible tokens and non-fungible tokens are treated equally, non-fungible tokens just have one max supply.
- Approval is set or unset to some operator over entire set of tokens. (More nuanced control is defined in [ERC1761](https://eips.ethereum.org/EIPS/eip-1761), do we want to merge them together?)
- Metadata and token enumeration should be done by indexing events off-chain.
- Mint and burn are mixed with transfer/send messages, otherwise, we'll have much more message types, e.g. `Mint`/`MintToContract`/`BatchMint`/`BatchMintToContract`, etc.
  In transfer/send messges, `from`/`to` are optional, a `None` `from` means minting, a `None` `to` means burning, they must not both be `None` at the same time.
  • Loading branch information
yihuang committed Mar 17, 2021
1 parent 0c3f3f5 commit f721945
Show file tree
Hide file tree
Showing 17 changed files with 802 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/cw0/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use cosmwasm_std::Attribute;

pub trait Event {
fn write_attributes(&self, attributes: &mut Vec<Attribute>);
}
2 changes: 2 additions & 0 deletions packages/cw0/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod balance;
mod event;
mod expiration;
mod pagination;
mod payment;
Expand All @@ -9,4 +10,5 @@ pub use pagination::{
pub use payment::{may_pay, must_pay, nonpayable, one_coin, PaymentError};

pub use crate::balance::NativeBalance;
pub use crate::event::Event;
pub use crate::expiration::{Duration, Expiration, DAY, HOUR, WEEK};
18 changes: 18 additions & 0 deletions packages/cw1155/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "cw1155"
version = "0.6.0-alpha1"
authors = ["Huang Yi <huang@crypto.com>"]
edition = "2018"
description = "Definition and types for the CosmWasm-1155 interface"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cosmwasm-plus"
homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"

[dependencies]
cosmwasm-std = { version = "0.14.0-beta1" }
schemars = "0.7"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }

[dev-dependencies]
cosmwasm-schema = { version = "0.14.0-alpha2" }
63 changes: 63 additions & 0 deletions packages/cw1155/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# CW1155 Spec: Multiple Tokens

CW1155 is a specification for managing multiple tokens based on CosmWasm.
The name and design is based on Ethereum's ERC1155 standard.

Design decisions:

- Fungible tokens and non-fungible tokens are treated equally, non-fungible tokens just have one max supply.

- Approval is set or unset to some operator over entire set of tokens. (More nuanced control is defined in [ERC1761](https://eips.ethereum.org/EIPS/eip-1761), do we want to merge them together?)

- Metadata and token enumeration should be done by indexing events off-chain.

- Mint and burn are mixed with transfer/send messages, otherwise, we'll have much more message types, e.g. `Mint`/`MintToContract`/`BatchMint`/`BatchMintToContract`, etc.

In transfer/send messges, `from`/`to` are optional, a `None` `from` means minting, a `None` `to` means burning, they must not both be `None` at the same time.

## Base

### Messages

`TransferFrom{from, to, token_id, value}` - This transfers some amount of tokens between two accounts. The operator should have approval from the source account.

`SendFrom{from, to, token_id, value, msg}` - This transfers some amount of tokens between two accounts. `to`
must be an address controlled by a smart contract, which implements
the `CW1155Receiver` interface. The operator should have approval from the source account. The `msg` will be passed to the recipient contract, along with the other fields.

`BatchTransferFrom{from, to, batch}` - Batched version of `TransferFrom` which can handle multiple types of tokens at once.

`BatchSendFrom{from, contract, batch, msg}` - Batched version of `SendFrom` which can handle multiple types of tokens at once.

`SetApprovalForAll { operator, approved }` - Grant or revoke `operator` the permission to transfer or send all tokens owned by `msg.sender`. This approval is tied to the owner, not the
tokens and applies to any future token that the owner receives as well.

### Queries

`Balance { owner, token_id }` - Query the balance of `owner` on perticular type of token, default to `0` when record not exist.

`BatchBalance { owner, token_ids }` - Query the balance of `owner` on multiple types of tokens, batched version of `Balance`

`ApprovedForAll{ owner, spender }` - Query if `spender` has the permission to transfer or send tokens owned by `msg.sender`.

### Receiver

Any contract wish to receive CW1155 tokens must implement `Cw1155ReceiveMsg` and `Cw1155BatchReceiveMsg`.

`Cw1155ReceiveMsg { operator, from, token_id, amount, msg}` -

`Cw1155BatchReceiveMsg { operator, from, batch, msg}` -

### Events

- `transfer(from, to, token_id, value)`

`from`/`to` are optional, no `from` attribute means minting, no `to` attribute means burning.

- `metadata(url, token_id)`

Metadata url of `token_id` is changed, `url` should point to a json file.

## Metadata and Enumerable

[TODO] ERC1155 suggests that metadata and enumerable should be indexed from events log, to save some on-chain storage. Should we define standard events like ERC1155?
21 changes: 21 additions & 0 deletions packages/cw1155/examples/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use std::env::current_dir;
use std::fs::create_dir_all;

use cosmwasm_schema::{export_schema, remove_schemas, schema_for};

use cw1155;

fn main() {
let mut out_dir = current_dir().unwrap();
out_dir.push("schema");
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();

export_schema(&schema_for!(cw1155::Cw1155HandleMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155QueryMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155ReceiveMsg), &out_dir);
export_schema(&schema_for!(cw1155::Cw1155BatchReceiveMsg), &out_dir);
export_schema(&schema_for!(cw1155::BalanceResponse), &out_dir);
export_schema(&schema_for!(cw1155::BatchBalanceResponse), &out_dir);
export_schema(&schema_for!(cw1155::ApprovedForAllResponse), &out_dir);
}
18 changes: 18 additions & 0 deletions packages/cw1155/schema/balance_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BalanceResponse",
"type": "object",
"required": [
"balance"
],
"properties": {
"balance": {
"$ref": "#/definitions/Uint128"
}
},
"definitions": {
"Uint128": {
"type": "string"
}
}
}
21 changes: 21 additions & 0 deletions packages/cw1155/schema/batch_balance_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BatchBalanceResponse",
"type": "object",
"required": [
"balances"
],
"properties": {
"balances": {
"type": "array",
"items": {
"$ref": "#/definitions/Uint128"
}
}
},
"definitions": {
"Uint128": {
"type": "string"
}
}
}
63 changes: 63 additions & 0 deletions packages/cw1155/schema/cw1155_batch_receive_msg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Cw1155BatchReceiveMsg",
"description": "Cw1155BatchReceiveMsg should be de/serialized under `BatchReceive()` variant in a HandleMsg",
"type": "object",
"required": [
"batch",
"operator"
],
"properties": {
"batch": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "string"
},
{
"$ref": "#/definitions/Uint128"
}
],
"maxItems": 2,
"minItems": 2
}
},
"from": {
"anyOf": [
{
"$ref": "#/definitions/HumanAddr"
},
{
"type": "null"
}
]
},
"msg": {
"anyOf": [
{
"$ref": "#/definitions/Binary"
},
{
"type": "null"
}
]
},
"operator": {
"$ref": "#/definitions/HumanAddr"
}
},
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>",
"type": "string"
},
"HumanAddr": {
"type": "string"
},
"Uint128": {
"type": "string"
}
}
}
Loading

0 comments on commit f721945

Please sign in to comment.