From 609c50ccb1db9342757ed084087f62875fbb64da Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Fri, 17 Feb 2023 00:19:19 +0700 Subject: [PATCH 1/4] validate royalty percentage when minting cw2981 --- contracts/cw2981-royalties/src/lib.rs | 72 ++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/contracts/cw2981-royalties/src/lib.rs b/contracts/cw2981-royalties/src/lib.rs index fa63d02b6..2a77017a3 100644 --- a/contracts/cw2981-royalties/src/lib.rs +++ b/contracts/cw2981-royalties/src/lib.rs @@ -4,7 +4,7 @@ pub mod query; pub use query::{check_royalties, query_royalties_info}; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_binary, Empty}; +use cosmwasm_std::{to_binary, Empty, StdError}; use cw2::set_contract_version; use cw721_base::Cw721Contract; pub use cw721_base::{ContractError, InstantiateMsg, MinterResponse}; @@ -80,7 +80,40 @@ pub mod entry { info: MessageInfo, msg: ExecuteMsg, ) -> Result { - Cw2981Contract::default().execute(deps, env, info, msg) + match msg { + ExecuteMsg::Mint { + token_id, + owner, + token_uri, + extension, + } => { + // validate royalty_percentage to be between 0 and 100 + if let Some(Metadata { + royalty_percentage: Some(royalty_percentage), + .. + }) = extension + { + // no need to check < 0 because royalty_percentage is u64 + if royalty_percentage > 100 { + return Err(ContractError::Std(StdError::GenericErr { + msg: "Royalty percentage must be between 0 and 100".to_string(), + })); + } + } + Cw2981Contract::default().execute( + deps, + env, + info, + cw721_base::ExecuteMsg::Mint { + token_id, + owner, + token_uri, + extension, + }, + ) + } + _ => Cw2981Contract::default().execute(deps, env, info, msg), + } } #[entry_point] @@ -143,6 +176,41 @@ mod tests { assert_eq!(res.extension, extension); } + #[test] + fn validate_royalty_information() { + let mut deps = mock_dependencies(); + let _contract = Cw2981Contract::default(); + + let info = mock_info(CREATOR, &[]); + let init_msg = InstantiateMsg { + name: "SpaceShips".to_string(), + symbol: "SPACE".to_string(), + minter: CREATOR.to_string(), + }; + entry::instantiate(deps.as_mut(), mock_env(), info.clone(), init_msg).unwrap(); + + let token_id = "Enterprise"; + let exec_msg = ExecuteMsg::Mint { + token_id: token_id.to_string(), + owner: "john".to_string(), + token_uri: Some("https://starships.example.com/Starship/Enterprise.json".into()), + extension: Some(Metadata { + description: Some("Spaceship with Warp Drive".into()), + name: Some("Starship USS Enterprise".to_string()), + royalty_percentage: Some(101), + ..Metadata::default() + }), + }; + // mint will return StdError + let err = entry::execute(deps.as_mut(), mock_env(), info, exec_msg).unwrap_err(); + assert_eq!( + err, + ContractError::Std(StdError::GenericErr { + msg: "Royalty percentage must be between 0 and 100".to_string(), + }) + ); + } + #[test] fn check_royalties_response() { let mut deps = mock_dependencies(); From db45da19e387d779992f076101e6137d85c1d8bd Mon Sep 17 00:00:00 2001 From: larry <26318510+larry0x@users.noreply.github.com> Date: Sat, 18 Feb 2023 15:53:19 +0000 Subject: [PATCH 2/4] custom error type --- Cargo.lock | 1 + contracts/cw2981-royalties/Cargo.toml | 1 + contracts/cw2981-royalties/src/error.rs | 14 ++++++ contracts/cw2981-royalties/src/lib.rs | 58 ++++++++----------------- 4 files changed, 35 insertions(+), 39 deletions(-) create mode 100644 contracts/cw2981-royalties/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 5df3b0adf..6751390c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -351,6 +351,7 @@ dependencies = [ "cw721-base 0.17.0", "schemars", "serde", + "thiserror", ] [[package]] diff --git a/contracts/cw2981-royalties/Cargo.toml b/contracts/cw2981-royalties/Cargo.toml index 4c265b469..d9140bc37 100644 --- a/contracts/cw2981-royalties/Cargo.toml +++ b/contracts/cw2981-royalties/Cargo.toml @@ -26,3 +26,4 @@ cw721 = { workspace = true } cw721-base = { workspace = true, features = ["library"] } schemars = { workspace = true } serde = { workspace = true } +thiserror = { workspace = true } diff --git a/contracts/cw2981-royalties/src/error.rs b/contracts/cw2981-royalties/src/error.rs new file mode 100644 index 000000000..9e7532435 --- /dev/null +++ b/contracts/cw2981-royalties/src/error.rs @@ -0,0 +1,14 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Debug, Error, PartialEq)] +pub enum ContractError { + #[error(transparent)] + Std(#[from] StdError), + + #[error(transparent)] + Base(#[from] cw721_base::ContractError), + + #[error("Royalty percentage must be between 0 and 100")] + InvalidRoyalty, +} diff --git a/contracts/cw2981-royalties/src/lib.rs b/contracts/cw2981-royalties/src/lib.rs index 2a77017a3..122a9115c 100644 --- a/contracts/cw2981-royalties/src/lib.rs +++ b/contracts/cw2981-royalties/src/lib.rs @@ -1,14 +1,16 @@ +pub mod error; pub mod msg; pub mod query; pub use query::{check_royalties, query_royalties_info}; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_binary, Empty, StdError}; +use cosmwasm_std::{to_binary, Empty}; use cw2::set_contract_version; use cw721_base::Cw721Contract; -pub use cw721_base::{ContractError, InstantiateMsg, MinterResponse}; +pub use cw721_base::{InstantiateMsg, MinterResponse}; +use crate::error::ContractError; use crate::msg::Cw2981QueryMsg; // Version info for migration @@ -80,40 +82,23 @@ pub mod entry { info: MessageInfo, msg: ExecuteMsg, ) -> Result { - match msg { - ExecuteMsg::Mint { - token_id, - owner, - token_uri, - extension, - } => { - // validate royalty_percentage to be between 0 and 100 - if let Some(Metadata { - royalty_percentage: Some(royalty_percentage), - .. - }) = extension - { - // no need to check < 0 because royalty_percentage is u64 - if royalty_percentage > 100 { - return Err(ContractError::Std(StdError::GenericErr { - msg: "Royalty percentage must be between 0 and 100".to_string(), - })); - } + if let ExecuteMsg::Mint { extension, .. } = &msg { + // validate royalty_percentage to be between 0 and 100 + if let Some(Metadata { + royalty_percentage: Some(royalty_percentage), + .. + }) = extension + { + // no need to check < 0 because royalty_percentage is u64 + if *royalty_percentage > 100 { + return Err(ContractError::InvalidRoyalty); } - Cw2981Contract::default().execute( - deps, - env, - info, - cw721_base::ExecuteMsg::Mint { - token_id, - owner, - token_uri, - extension, - }, - ) } - _ => Cw2981Contract::default().execute(deps, env, info, msg), } + + Cw2981Contract::default() + .execute(deps, env, info, msg) + .map_err(Into::into) } #[entry_point] @@ -203,12 +188,7 @@ mod tests { }; // mint will return StdError let err = entry::execute(deps.as_mut(), mock_env(), info, exec_msg).unwrap_err(); - assert_eq!( - err, - ContractError::Std(StdError::GenericErr { - msg: "Royalty percentage must be between 0 and 100".to_string(), - }) - ); + assert_eq!(err, ContractError::InvalidRoyalty); } #[test] From 21471b91320fbc62f986e20da8f4550e62e8ed51 Mon Sep 17 00:00:00 2001 From: larry <26318510+larry0x@users.noreply.github.com> Date: Sat, 18 Feb 2023 15:56:26 +0000 Subject: [PATCH 3/4] rename the error name --- contracts/cw2981-royalties/src/error.rs | 2 +- contracts/cw2981-royalties/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/cw2981-royalties/src/error.rs b/contracts/cw2981-royalties/src/error.rs index 9e7532435..73c0e4bb4 100644 --- a/contracts/cw2981-royalties/src/error.rs +++ b/contracts/cw2981-royalties/src/error.rs @@ -10,5 +10,5 @@ pub enum ContractError { Base(#[from] cw721_base::ContractError), #[error("Royalty percentage must be between 0 and 100")] - InvalidRoyalty, + InvalidRoyaltyPercentage, } diff --git a/contracts/cw2981-royalties/src/lib.rs b/contracts/cw2981-royalties/src/lib.rs index 122a9115c..209aaeebf 100644 --- a/contracts/cw2981-royalties/src/lib.rs +++ b/contracts/cw2981-royalties/src/lib.rs @@ -91,7 +91,7 @@ pub mod entry { { // no need to check < 0 because royalty_percentage is u64 if *royalty_percentage > 100 { - return Err(ContractError::InvalidRoyalty); + return Err(ContractError::InvalidRoyaltyPercentage); } } } @@ -188,7 +188,7 @@ mod tests { }; // mint will return StdError let err = entry::execute(deps.as_mut(), mock_env(), info, exec_msg).unwrap_err(); - assert_eq!(err, ContractError::InvalidRoyalty); + assert_eq!(err, ContractError::InvalidRoyaltyPercentage); } #[test] From b8c58b52152dcce9d049290402721e14ffa214d8 Mon Sep 17 00:00:00 2001 From: larry <26318510+larry0x@users.noreply.github.com> Date: Sat, 18 Feb 2023 16:00:48 +0000 Subject: [PATCH 4/4] fix a clippy warning --- contracts/cw2981-royalties/src/lib.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/contracts/cw2981-royalties/src/lib.rs b/contracts/cw2981-royalties/src/lib.rs index 209aaeebf..aa9e92b6d 100644 --- a/contracts/cw2981-royalties/src/lib.rs +++ b/contracts/cw2981-royalties/src/lib.rs @@ -82,17 +82,19 @@ pub mod entry { info: MessageInfo, msg: ExecuteMsg, ) -> Result { - if let ExecuteMsg::Mint { extension, .. } = &msg { + if let ExecuteMsg::Mint { + extension: + Some(Metadata { + royalty_percentage: Some(royalty_percentage), + .. + }), + .. + } = &msg + { // validate royalty_percentage to be between 0 and 100 - if let Some(Metadata { - royalty_percentage: Some(royalty_percentage), - .. - }) = extension - { - // no need to check < 0 because royalty_percentage is u64 - if *royalty_percentage > 100 { - return Err(ContractError::InvalidRoyaltyPercentage); - } + // no need to check < 0 because royalty_percentage is u64 + if *royalty_percentage > 100 { + return Err(ContractError::InvalidRoyaltyPercentage); } }