Repository: public-awesome/launchpad (rust)

Issue:
Fix Launchpad base-minter bug
minting is permissionless. should restrict to creator

Pull request:
check privileges for minting 1:1's
fix #366

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 1efe4036..29ac48d4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -60,7 +60,8 @@ dependencies = [
  "sg2",
  "sg4",
  "sg721 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sg721-nt 0.13.1",
+ "sg721-base 0.14.0",
+ "sg721-nt",
  "thiserror",
  "url",
 ]
@@ -1059,27 +1060,6 @@ dependencies = [
  "sg721-base 0.14.0",
 ]
 
-[[package]]
-name = "sg721-nt"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "394bf96e6ebd4db0e459e1ef488ac85de554c8f191a996b343421aa7a714741d"
-dependencies = [
- "cosmwasm-std",
- "cw-storage-plus",
- "cw-utils",
- "cw2",
- "cw721",
- "cw721-base",
- "schemars",
- "serde",
- "sg-std 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sg721 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sg721-base 0.13.1",
- "thiserror",
- "url",
-]
-
 [[package]]
 name = "sg721-nt"
 version = "0.14.0"
diff --git a/contracts/base-minter/Cargo.toml b/contracts/base-minter/Cargo.toml
index 7be9eecb..8619ecf3 100644
--- a/contracts/base-minter/Cargo.toml
+++ b/contracts/base-minter/Cargo.toml
@@ -44,6 +44,7 @@ cw721 = "0.13.4"
 cw721-base = { version = "0.13.4", features = ["library"] }
 sg1 = "0.14.1"
 sg721 = "0.14.0"
+sg721-base = { path = "../sg721-base" }
 base-factory = { path = "../base-factory" }
 sg2 = { path = "../../packages/sg2" }
 sg4 = { path = "../../packages/sg4" }
@@ -52,4 +53,4 @@ sg4 = { path = "../../packages/sg4" }
 cosmwasm-schema = { version = "1.0.0" }
 cw-multi-test = "0.13.4"
 sg-multi-test = "0.15.1"
-sg721-nt = { version = "0.13.1", features = ["library"] }
+sg721-nt = { path = "../sg721-nt"}
diff --git a/contracts/base-minter/src/contract.rs b/contracts/base-minter/src/contract.rs
index e8fd57f3..5d4b2ac6 100644
--- a/contracts/base-minter/src/contract.rs
+++ b/contracts/base-minter/src/contract.rs
@@ -19,6 +19,7 @@ use sg1::checked_fair_burn;
 use sg2::query::Sg2QueryMsg;
 use sg4::{QueryMsg, Status, StatusResponse, SudoMsg};
 use sg721::{ExecuteMsg as Sg721ExecuteMsg, InstantiateMsg as Sg721InstantiateMsg};
+use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg};
 use sg_std::math::U64Ext;
 use sg_std::{Response, SubMsg, NATIVE_DENOM};
 use url::Url;
@@ -102,7 +103,20 @@ pub fn execute_mint_sender(
     token_uri: String,
 ) -> Result<Response, ContractError> {
     let config = CONFIG.load(deps.storage)?;
-    let collection = COLLECTION_ADDRESS.load(deps.storage)?;
+    let collection_address = COLLECTION_ADDRESS.load(deps.storage)?;
+
+    // This is a 1:1 minter, minted at min_mint_price
+    // Should mint and then list on the marketplace for secondary sales
+    let collection_info: CollectionInfoResponse = deps.querier.query_wasm_smart(
+        collection_address.clone(),
+        &Sg721QueryMsg::CollectionInfo {},
+    )?;
+    // allow only sg721 creator address to mint
+    if collection_info.creator != info.sender {
+        return Err(ContractError::Unauthorized(
+            "Sender is not sg721 creator".to_owned(),
+        ));
+    };
 
     let parsed_token_uri = Url::parse(&token_uri)?;
     if parsed_token_uri.scheme() != "ipfs" {
@@ -135,7 +149,7 @@ pub fn execute_mint_sender(
         extension: None,
     });
     let msg = CosmosMsg::Wasm(WasmMsg::Execute {
-        contract_addr: collection.to_string(),
+        contract_addr: collection_address.to_string(),
         msg: to_binary(&mint_msg)?,
         funds: vec![],
     });
diff --git a/contracts/sg721-nt/Cargo.toml b/contracts/sg721-nt/Cargo.toml
index 0447eeae..1aedc944 100644
--- a/contracts/sg721-nt/Cargo.toml
+++ b/contracts/sg721-nt/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "sg721-nt"
 version = "0.14.0"
-authors = ["Shane Vitarana <s@noreply.publicawesome.com>"]
+authors = ["Shane Vitarana <s@noreply.publicawesome.com>", "John Y <j@noreply.publicawesome.com>"]
 edition = "2018"
 description = "Stargaze Non-transferrable NFT collection contract"
 license = "Apache-2.0"
diff --git a/contracts/sg721-nt/src/lib.rs b/contracts/sg721-nt/src/lib.rs
index 26698998..d8331f08 100644
--- a/contracts/sg721-nt/src/lib.rs
+++ b/contracts/sg721-nt/src/lib.rs
@@ -9,7 +9,7 @@ pub mod msg;
 use cw721_base::Extension;
 use sg721::InstantiateMsg;
 use sg721_base::Sg721Contract;
-
+pub type QueryMsg = sg721_base::msg::QueryMsg;
 pub type Sg721NonTransferableContract<'a> = Sg721Contract<'a, Extension>;
 
 #[cfg(not(feature = "library"))]
@@ -17,7 +17,7 @@ pub mod entry {
     use super::*;
 
     use crate::msg::ExecuteMsg;
-    use cosmwasm_std::{DepsMut, Env, MessageInfo};
+    use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, StdResult};
     use sg721_base::ContractError;
     use sg_std::Response;
 
@@ -54,4 +54,9 @@ pub mod entry {
             }
         }
     }
+
+    #[entry_point]
+    pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
+        Sg721NonTransferableContract::default().query(deps, env, msg)
+    }
 }


Test patch:
diff --git a/contracts/base-minter/src/integration_tests.rs b/contracts/base-minter/src/integration_tests.rs
index 3ac62b74..cc3da3dd 100644
--- a/contracts/base-minter/src/integration_tests.rs
+++ b/contracts/base-minter/src/integration_tests.rs
@@ -39,7 +39,7 @@ pub fn contract_minter() -> Box<dyn Contract<StargazeMsgWrapper>> {
 }
 
 /// non-transferable nft
-pub fn contract_collection() -> Box<dyn Contract<StargazeMsgWrapper>> {
+pub fn nt_contract_collection() -> Box<dyn Contract<StargazeMsgWrapper>> {
     let contract = ContractWrapper::new(
         sg721_nt::entry::execute,
         sg721_nt::entry::instantiate,
@@ -86,7 +86,7 @@ fn setup_minter_contract(router: &mut StargazeApp, creator: &Addr) -> (Addr, Con
         )
         .unwrap();
 
-    let collection_code_id = router.store_code(contract_collection());
+    let collection_code_id = router.store_code(nt_contract_collection());
 
     let mut msg = mock_create_minter();
     msg.collection_params.code_id = collection_code_id;
@@ -118,8 +118,9 @@ fn setup_minter_contract(router: &mut StargazeApp, creator: &Addr) -> (Addr, Con
 }
 
 // Add a creator account with initial balances
-fn setup_accounts(router: &mut StargazeApp) -> Addr {
+fn setup_accounts(router: &mut StargazeApp) -> (Addr, Addr) {
     let creator = Addr::unchecked("creator");
+    let buyer = Addr::unchecked("buyer");
     // 3,000 tokens
     let creator_funds = coins(INITIAL_BALANCE, NATIVE_DENOM);
     router
@@ -135,13 +136,23 @@ fn setup_accounts(router: &mut StargazeApp) -> Addr {
     let creator_native_balances = router.wrap().query_all_balances(creator.clone()).unwrap();
     assert_eq!(creator_native_balances, creator_funds);
 
-    creator
+    router
+        .sudo(SudoMsg::Bank({
+            BankSudo::Mint {
+                to_address: buyer.to_string(),
+                amount: creator_funds,
+            }
+        }))
+        .map_err(|err| println!("{:?}", err))
+        .ok();
+
+    (creator, buyer)
 }
 
 #[test]
 fn check_mint() {
     let mut router = custom_mock_app();
-    let creator = setup_accounts(&mut router);
+    let (creator, buyer) = setup_accounts(&mut router);
     let (minter_addr, config) = setup_minter_contract(&mut router, &creator);
 
     // Fail with incorrect token uri
@@ -163,6 +174,18 @@ fn check_mint() {
     );
     assert!(err.is_err());
 
+    // Not authorized to mint
+    let mint_msg = ExecuteMsg::Mint {
+        token_uri: "ipfs://example".to_string(),
+    };
+    let err = router.execute_contract(
+        buyer,
+        minter_addr.clone(),
+        &mint_msg,
+        &[coin(MIN_MINT_PRICE, NATIVE_DENOM)],
+    );
+    assert!(err.is_err());
+
     // Succeeds if funds are sent
     let mint_msg = ExecuteMsg::Mint {
         token_uri: "ipfs://example".to_string(),