Skip to content

Commit

Permalink
Merge pull request #586 from public-awesome/serkan/v1-royalty-increase
Browse files Browse the repository at this point in the history
Royalty increase option for v1 collections
  • Loading branch information
MightOfOaks authored Jun 29, 2023
2 parents 2014940 + 80c84fe commit f9b1c54
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

237 changes: 221 additions & 16 deletions contracts/minter/src/contract_updatable_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ pub fn contract_sg721() -> Box<dyn Contract<StargazeMsgWrapper>> {
Box::new(contract)
}

pub fn contract_sg721_base() -> Box<dyn Contract<StargazeMsgWrapper>> {
let contract = ContractWrapper::new(
sg721::contract::execute,
sg721::contract::instantiate,
sg721::contract::query,
);
Box::new(contract)
}

fn setup_whitelist_contract(router: &mut StargazeApp, creator: &Addr) -> Addr {
let whitelist_code_id = router.store_code(contract_whitelist());

Expand Down Expand Up @@ -1450,7 +1459,7 @@ fn test_update_none_royalties() {
let mut router = custom_mock_app();
let (creator, buyer) = setup_accounts(&mut router);
let num_tokens = 10;

setup_block_time(&mut router, GENESIS_MINT_START_TIME);
// Upload contract code
let sg721_code_id = router.store_code(contract_sg721());
let minter_code_id = router.store_code(contract_minter());
Expand Down Expand Up @@ -1513,26 +1522,121 @@ fn test_update_none_royalties() {
sg721_updatable::ContractError::Unauthorized {}.to_string()
);

let update_royalty_msg: Sg721UpdatableExecuteMsg<Extension> =
Sg721UpdatableExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 1200,
};

let res = router.execute_contract(
creator,
Addr::unchecked(sg71_address),
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
);
let err = res.unwrap_err();

assert_eq!(
err.source().unwrap().to_string(),
sg721_updatable::ContractError::RoyaltyShareIncreased {}.to_string()
sg721_updatable::ContractError::RoyaltyShareIncreasedTooMuch {}.to_string()
);

let update_royalty_msg: Sg721UpdatableExecuteMsg<Extension> =
Sg721UpdatableExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 400,
};

let res = router
.execute_contract(
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
)
.unwrap();

assert_eq!(res.events[1].attributes[0].key, "_contract_addr");
assert_eq!(res.events[1].attributes[0].value, "contract1");
assert_eq!(res.events[1].attributes[1].key, "sender");
assert_eq!(res.events[1].attributes[1].value, "creator");
assert_eq!(res.events[1].attributes[2].key, "payment_address");
assert_eq!(res.events[1].attributes[2].value, "creator2");
assert_eq!(res.events[1].attributes[3].key, "share");
assert_eq!(res.events[1].attributes[3].value, "0.04");

let update_royalty_msg: Sg721UpdatableExecuteMsg<Extension> =
Sg721UpdatableExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 500,
};

let res = router.execute_contract(
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
);
let err = res.unwrap_err();

assert_eq!(
err.source().unwrap().to_string(),
sg721_updatable::ContractError::RoyaltyUpdateTooSoon {}.to_string()
);

setup_block_time(&mut router, GENESIS_MINT_START_TIME + 86400000000000);

let res = router
.execute_contract(
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
)
.unwrap();

assert_eq!(res.events[1].attributes[0].key, "_contract_addr");
assert_eq!(res.events[1].attributes[0].value, "contract1");
assert_eq!(res.events[1].attributes[1].key, "sender");
assert_eq!(res.events[1].attributes[1].value, "creator");
assert_eq!(res.events[1].attributes[2].key, "payment_address");
assert_eq!(res.events[1].attributes[2].value, "creator2");
assert_eq!(res.events[1].attributes[3].key, "share");
assert_eq!(res.events[1].attributes[3].value, "0.05");

setup_block_time(&mut router, GENESIS_MINT_START_TIME + 86500000000000);

let update_royalty_msg: Sg721UpdatableExecuteMsg<Extension> =
Sg721UpdatableExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 300,
};

let res = router
.execute_contract(
creator,
Addr::unchecked(sg71_address),
&update_royalty_msg,
&[],
)
.unwrap();

assert_eq!(res.events[1].attributes[0].key, "_contract_addr");
assert_eq!(res.events[1].attributes[0].value, "contract1");
assert_eq!(res.events[1].attributes[1].key, "sender");
assert_eq!(res.events[1].attributes[1].value, "creator");
assert_eq!(res.events[1].attributes[2].key, "payment_address");
assert_eq!(res.events[1].attributes[2].value, "creator2");
assert_eq!(res.events[1].attributes[3].key, "share");
assert_eq!(res.events[1].attributes[3].value, "0.03");
}

#[test]
fn test_update_royalties() {
let mut router = custom_mock_app();
let (creator, _) = setup_accounts(&mut router);
let num_tokens = 10;

setup_block_time(&mut router, GENESIS_MINT_START_TIME);
// Upload contract code
let sg721_code_id = router.store_code(contract_sg721());
let minter_code_id = router.store_code(contract_minter());
Expand All @@ -1558,7 +1662,7 @@ fn test_update_royalties() {
external_link: Some("https://example.com/external.html".to_string()),
royalty_info: Some(RoyaltyInfoResponse {
payment_address: creator.to_string(),
share: Decimal::percent(10),
share: Decimal::percent(5),
}),
},
},
Expand Down Expand Up @@ -1595,14 +1699,45 @@ fn test_update_royalties() {

assert_eq!(
err.source().unwrap().to_string(),
sg721_updatable::ContractError::RoyaltyShareIncreased {}.to_string()
sg721_updatable::ContractError::RoyaltyShareIncreasedTooMuch {}.to_string()
);

let update_royalty_msg: sg721_updatable::msg::ExecuteMsg<Extension> =
sg721_updatable::msg::ExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 900,
};
let res = router.execute_contract(
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
);

let err = res.unwrap_err();

assert_eq!(
err.source().unwrap().to_string(),
sg721_updatable::ContractError::RoyaltyUpdateTooSoon {}.to_string()
);

setup_block_time(&mut router, GENESIS_MINT_START_TIME + 86400000000000);

let res = router.execute_contract(
creator.clone(),
Addr::unchecked(sg71_address.clone()),
&update_royalty_msg,
&[],
);
assert!(res.is_ok());

setup_block_time(&mut router, GENESIS_MINT_START_TIME + 86500000000000);

let update_royalty_msg: sg721_updatable::msg::ExecuteMsg<Extension> =
sg721_updatable::msg::ExecuteMsg::UpdateRoyaltyInfo {
payment_address: "creator2".to_string(),
share_bps: 800,
};
let res = router.execute_contract(
creator,
Addr::unchecked(sg71_address),
Expand Down Expand Up @@ -1725,14 +1860,84 @@ fn try_migrate() {
);

// // no op when same version
set_contract_version(
&mut deps.storage,
"crates.io:sg-721",
env!("CARGO_PKG_VERSION"),
)
.unwrap();
sg721_updatable::contract::migrate(deps.as_mut(), env.clone(), Empty {}).unwrap();

set_contract_version(&mut deps.storage, "crates.io:sg721-updatable", "0.8.0").unwrap();
set_contract_version(&mut deps.storage, "crates.io:sg-721", "0.8.4").unwrap();
sg721_updatable::contract::migrate(deps.as_mut(), env, Empty {}).unwrap();

// Migration happy path
let mut router = custom_mock_app();
let (creator, _) = setup_accounts(&mut router);
let num_tokens = 10;
// Upload contract code
let sg721_base_code_id = router.store_code(contract_sg721_base());
let sg721_code_id = router.store_code(contract_sg721());
let minter_code_id = router.store_code(contract_minter());
let creation_fee = coins(CREATION_FEE, NATIVE_DENOM);

// Instantiate minter
let msg = InstantiateMsg {
unit_price: coin(UNIT_PRICE, NATIVE_DENOM),
num_tokens,
start_time: Timestamp::from_nanos(GENESIS_MINT_START_TIME),
per_address_limit: 5,
whitelist: None,
base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(),
sg721_code_id: sg721_base_code_id,
sg721_instantiate_msg: Sg721InstantiateMsg {
name: String::from("TEST"),
symbol: String::from("TEST"),
minter: creator.to_string(),
collection_info: CollectionInfo {
creator: creator.to_string(),
description: String::from("Stargaze Monkeys"),
image: "https://example.com/image.png".to_string(),
external_link: Some("https://example.com/external.html".to_string()),
royalty_info: Some(RoyaltyInfoResponse {
payment_address: creator.to_string(),
share: Decimal::percent(5),
}),
},
},
};
let minter_addr = router
.instantiate_contract(
minter_code_id,
creator.clone(),
&msg,
&creation_fee,
"Minter",
None,
)
.unwrap();
let config: ConfigResponse = router
.wrap()
.query_wasm_smart(minter_addr, &QueryMsg::Config {})
.unwrap();

let sg721_base_address = config.sg721_address;

let collection_info: CollectionInfo<sg721_updatable::msg::RoyaltyInfoResponse> = router
.wrap()
.query_wasm_smart(
sg721_base_address.clone(),
&sg721::msg::QueryMsg::CollectionInfo {},
)
.unwrap();

assert!(collection_info.royalty_info.unwrap().updated_at.is_none());

router
.migrate_contract(
creator,
Addr::unchecked(sg721_base_address.clone()),
&Empty {},
sg721_code_id,
)
.unwrap();

let collection_info: CollectionInfo<sg721_updatable::msg::RoyaltyInfoResponse> = router
.wrap()
.query_wasm_smart(sg721_base_address, &sg721::msg::QueryMsg::CollectionInfo {})
.unwrap();

assert!(collection_info.royalty_info.unwrap().updated_at.is_some(),);
}
2 changes: 1 addition & 1 deletion contracts/royalty-group/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ pub fn execute_distribute_funds(
let attributes = vec![
attr("action", "distribute_funds"),
attr("funds", funds.to_string()),
attr("sender", &info.sender),
attr("sender", info.sender),
];

Ok(Response::new()
Expand Down
2 changes: 1 addition & 1 deletion contracts/sg721-updatable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sg721-updatable"
version = "0.8.3"
version = "0.8.4"
authors = ["John Y <[email protected]>"]
edition = "2018"

Expand Down
22 changes: 22 additions & 0 deletions contracts/sg721-updatable/schema/collection_info_response.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,30 @@
},
"share": {
"$ref": "#/definitions/Decimal"
},
"updated_at": {
"anyOf": [
{
"$ref": "#/definitions/Timestamp"
},
{
"type": "null"
}
]
}
}
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}
22 changes: 22 additions & 0 deletions contracts/sg721-updatable/schema/instantiate_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,30 @@
},
"share": {
"$ref": "#/definitions/Decimal"
},
"updated_at": {
"anyOf": [
{
"$ref": "#/definitions/Timestamp"
},
{
"type": "null"
}
]
}
}
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}
Loading

0 comments on commit f9b1c54

Please sign in to comment.