Skip to content

Commit

Permalink
Merge pull request #24 from CosmWasm/cw2981_extension
Browse files Browse the repository at this point in the history
CW-2981 extension
  • Loading branch information
the-frey authored Jan 13, 2022
2 parents 0ac4043 + ea94e4d commit d1a3631
Show file tree
Hide file tree
Showing 24 changed files with 1,999 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ target/
.vscode/
.idea/
*.iml
\#*\#
.\#*

# Auto-gen
.cargo-ok
Expand Down
41 changes: 31 additions & 10 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 contracts/cw2981-royalties/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --example schema"
36 changes: 36 additions & 0 deletions contracts/cw2981-royalties/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "cw2981-royalties"
version = "0.10.0"
authors = ["Alex Lynham <alex@lynh.am>"]
edition = "2018"
description = "Basic implementation of royalties for cw721 NFTs with token level royalties"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cw-nfts"
homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"artifacts/*",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[dependencies]
cw721 = { path = "../../packages/cw721", version = "0.11" }
cw721-base = { path = "../cw721-base", version = "0.11", features = ["library"] }
cosmwasm-std = { version = "1.0.0-beta" }
schemars = "0.8.1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.23" }

[dev-dependencies]
cosmwasm-schema = { version = "0.16.0" }
14 changes: 14 additions & 0 deletions contracts/cw2981-royalties/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CW-2981 Token-level Royalties
Copyright (C) 2021 Envoy Labs Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
65 changes: 65 additions & 0 deletions contracts/cw2981-royalties/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# CW-2981 Token-level Royalties

An example of porting EIP-2981 to implement royalties at a token mint level.

Builds on top of the metadata pattern in `cw721-metadata-onchain`.

All of the CW-721 logic and behaviour you would expect for an NFT is implemented as normal, but additionally at mint time, royalty information can be attached to a token.

Exposes two new query message types that can be called:

```rust
// Should be called on sale to see if royalties are owed
// by the marketplace selling the NFT.
// See https://eips.ethereum.org/EIPS/eip-2981
RoyaltyInfo {
token_id: String,
// the denom of this sale must also be the denom returned by RoyaltiesInfoResponse
sale_price: Uint128,
},
// Called against the contract to signal that CW-2981 is implemented
CheckRoyalties {},
```

The responses are:

```rust
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct RoyaltiesInfoResponse {
pub address: String,
// Note that this must be the same denom as that passed in to RoyaltyInfo
// rounding up or down is at the discretion of the implementer
pub royalty_amount: Uint128,
}

/// Shows if the contract implements royalties
/// if royalty_payments is true, marketplaces should pay them
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct CheckRoyaltiesResponse {
pub royalty_payments: bool,
}
```


To set this information, new meta fields are available on mint:

```rust
/// specify whether royalties are set on this token
pub royalty_payments: bool,
/// This is how much the minter takes as a cut when sold
pub royalty_percentage: Option<u64>,
/// The payment address, may be different to or the same
/// as the minter addr
/// question: how do we validate this?
pub royalty_payment_address: Option<String>,
```

Note that the `royalty_payment_address` could of course be a single address, a multisig, or a DAO.

## A note on CheckRoyalties

For this contract, there's nothing to check. This hook is expected to be present to check if the contract does implement CW2981 and signal that on sale royalties should be checked. With the implementation at token level it should always return true because it's up to the token.

Of course contracts that extend this can determine their own behaviour and replace this function if they have more complex behaviour (for example, you could maintain a secondary index of which tokens actually have royalties).

In this super simple case that isn't necessary.
42 changes: 42 additions & 0 deletions contracts/cw2981-royalties/examples/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::env::current_dir;
use std::fs::create_dir_all;

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

use cw721::{
AllNftInfoResponse, ContractInfoResponse, NftInfoResponse, NumTokensResponse,
OperatorsResponse, OwnerOfResponse, TokensResponse,
};
use cw721_base::{ExecuteMsg, Extension, InstantiateMsg, MinterResponse, QueryMsg};

use cw2981_royalties::msg::{CheckRoyaltiesResponse, Cw2981QueryMsg, RoyaltiesInfoResponse};

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!(InstantiateMsg), &out_dir);
export_schema_with_title(&schema_for!(ExecuteMsg<Extension>), &out_dir, "ExecuteMsg");
export_schema(&schema_for!(QueryMsg), &out_dir);
export_schema_with_title(
&schema_for!(AllNftInfoResponse<Extension>),
&out_dir,
"AllNftInfoResponse",
);
export_schema(&schema_for!(OperatorsResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse), &out_dir);
export_schema(&schema_for!(MinterResponse), &out_dir);
export_schema_with_title(
&schema_for!(NftInfoResponse<Extension>),
&out_dir,
"NftInfoResponse",
);
export_schema(&schema_for!(NumTokensResponse), &out_dir);
export_schema(&schema_for!(OwnerOfResponse), &out_dir);
export_schema(&schema_for!(TokensResponse), &out_dir);
export_schema(&schema_for!(Cw2981QueryMsg), &out_dir);
export_schema(&schema_for!(RoyaltiesInfoResponse), &out_dir);
export_schema(&schema_for!(CheckRoyaltiesResponse), &out_dir);
}
Loading

0 comments on commit d1a3631

Please sign in to comment.