From ea7f2bfcfd1cb035b836a1b72aaebf2e0694248f Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 13:08:21 -0800 Subject: [PATCH 01/42] copy file structure --- contracts/sg-eth-airdrop/src/bin/schema.rs | 2 +- contracts/sg-eth-airdrop/src/dydx_airdrop.rs | 0 contracts/sg-eth-airdrop/src/lib.rs | 10 ++-------- contracts/sg-eth-airdrop/src/rekt_airdrop.rs | 8 ++++++++ .../src/{ => rekt_airdrop}/claim_airdrop.rs | 10 +++++----- .../sg-eth-airdrop/src/{ => rekt_airdrop}/contract.rs | 10 +++++----- .../sg-eth-airdrop/src/{ => rekt_airdrop}/error.rs | 0 contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/msg.rs | 0 .../sg-eth-airdrop/src/{ => rekt_airdrop}/query.rs | 2 +- .../sg-eth-airdrop/src/{ => rekt_airdrop}/reply.rs | 4 ++-- .../sg-eth-airdrop/src/{ => rekt_airdrop}/state.rs | 0 .../sg-eth-airdrop/src/{ => rekt_airdrop}/testing.rs | 0 test-suite/src/common_setup/contract_boxes.rs | 8 ++++---- .../setup/collection_whitelist_helpers.rs | 2 +- test-suite/src/sg_eth_airdrop/setup/execute_msg.rs | 2 +- .../src/sg_eth_airdrop/setup/mock_minter_contract.rs | 2 +- .../sg_eth_airdrop/setup/mock_whitelist_contract.rs | 2 +- test-suite/src/sg_eth_airdrop/tests/test_claim.rs | 4 ++-- .../sg_eth_airdrop/tests/test_collection_whitelist.rs | 4 ++-- .../sg_eth_airdrop/tests/test_immutable_whitelist.rs | 6 +++--- 20 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop.rs create mode 100644 contracts/sg-eth-airdrop/src/rekt_airdrop.rs rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/claim_airdrop.rs (94%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/contract.rs (95%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/error.rs (100%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/msg.rs (100%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/query.rs (96%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/reply.rs (93%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/state.rs (100%) rename contracts/sg-eth-airdrop/src/{ => rekt_airdrop}/testing.rs (100%) diff --git a/contracts/sg-eth-airdrop/src/bin/schema.rs b/contracts/sg-eth-airdrop/src/bin/schema.rs index 19a0a98f5..3560190b9 100644 --- a/contracts/sg-eth-airdrop/src/bin/schema.rs +++ b/contracts/sg-eth-airdrop/src/bin/schema.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::write_api; -use sg_eth_airdrop::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; fn main() { write_api! { diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop.rs new file mode 100644 index 000000000..e69de29bb diff --git a/contracts/sg-eth-airdrop/src/lib.rs b/contracts/sg-eth-airdrop/src/lib.rs index 76387429a..3abd8698a 100644 --- a/contracts/sg-eth-airdrop/src/lib.rs +++ b/contracts/sg-eth-airdrop/src/lib.rs @@ -1,8 +1,2 @@ -pub mod contract; -pub mod error; -pub mod msg; -pub mod query; -pub mod reply; -pub mod state; -pub use crate::error::ContractError; -mod claim_airdrop; +pub mod dydx_airdrop; +pub mod rekt_airdrop; diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop.rs new file mode 100644 index 000000000..48e0a4163 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/rekt_airdrop.rs @@ -0,0 +1,8 @@ +pub mod contract; +pub mod error; +pub mod msg; +pub mod query; +pub mod reply; +pub mod state; +pub use crate::rekt_airdrop::error::ContractError; +mod claim_airdrop; diff --git a/contracts/sg-eth-airdrop/src/claim_airdrop.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs similarity index 94% rename from contracts/sg-eth-airdrop/src/claim_airdrop.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs index 7ac8d199a..816766a40 100644 --- a/contracts/sg-eth-airdrop/src/claim_airdrop.rs +++ b/contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs @@ -1,6 +1,6 @@ -use crate::query::query_collection_whitelist; -use crate::state::ADDRS_TO_MINT_COUNT; -use crate::{state::CONFIG, ContractError}; +use crate::rekt_airdrop::query::query_collection_whitelist; +use crate::rekt_airdrop::state::ADDRS_TO_MINT_COUNT; +use crate::rekt_airdrop::{state::CONFIG, ContractError}; use build_messages::claim_and_whitelist_add; use cosmwasm_std::DepsMut; use cosmwasm_std::{coins, Addr, BankMsg, StdResult}; @@ -88,8 +88,8 @@ mod validation { use ethereum_verify::verify_ethereum_text; use crate::{ - query::{query_airdrop_is_eligible, query_per_address_limit}, - state::Config, + rekt_airdrop::query::{query_airdrop_is_eligible, query_per_address_limit}, + rekt_airdrop::state::Config, }; pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { diff --git a/contracts/sg-eth-airdrop/src/contract.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs similarity index 95% rename from contracts/sg-eth-airdrop/src/contract.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs index 9e78689ed..9807ffb4a 100644 --- a/contracts/sg-eth-airdrop/src/contract.rs +++ b/contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs @@ -1,8 +1,8 @@ -use crate::claim_airdrop::claim_airdrop; +use crate::rekt_airdrop::claim_airdrop::claim_airdrop; #[cfg(not(feature = "library"))] -use crate::error::ContractError; -use crate::msg::{ExecuteMsg, InstantiateMsg}; -use crate::state::CONFIG; +use crate::rekt_airdrop::error::ContractError; +use crate::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg}; +use crate::rekt_airdrop::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, MessageInfo}; @@ -55,7 +55,7 @@ pub fn execute( mod build_message { use super::*; - use crate::state::Config; + use crate::rekt_airdrop::state::Config; use cosmwasm_std::{to_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; diff --git a/contracts/sg-eth-airdrop/src/error.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/error.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/error.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/error.rs diff --git a/contracts/sg-eth-airdrop/src/msg.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/msg.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/msg.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/msg.rs diff --git a/contracts/sg-eth-airdrop/src/query.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs similarity index 96% rename from contracts/sg-eth-airdrop/src/query.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs index c3b50fcd1..d1c34cd5c 100644 --- a/contracts/sg-eth-airdrop/src/query.rs +++ b/contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs @@ -1,4 +1,4 @@ -use crate::{msg::QueryMsg, state::CONFIG, ContractError}; +use crate::rekt_airdrop::{msg::QueryMsg, state::CONFIG, ContractError}; use cosmwasm_std::{entry_point, to_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; diff --git a/contracts/sg-eth-airdrop/src/reply.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs similarity index 93% rename from contracts/sg-eth-airdrop/src/reply.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs index 90f98d77b..cd4d40ada 100644 --- a/contracts/sg-eth-airdrop/src/reply.rs +++ b/contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] -use crate::error::ContractError; -use crate::state::CONFIG; +use crate::rekt_airdrop::error::ContractError; +use crate::rekt_airdrop::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, Reply}; use cw_utils::{parse_reply_instantiate_data, MsgInstantiateContractResponse, ParseReplyError}; diff --git a/contracts/sg-eth-airdrop/src/state.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/state.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/state.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/state.rs diff --git a/contracts/sg-eth-airdrop/src/testing.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/testing.rs rename to contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 65a9fd3d0..2a19ef8e4 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -123,11 +123,11 @@ pub fn contract_group() -> Box> { pub fn contract_eth_airdrop() -> Box> { let contract = ContractWrapper::new( - sg_eth_airdrop::contract::execute, - sg_eth_airdrop::contract::instantiate, - sg_eth_airdrop::query::query, + sg_eth_airdrop::rekt_airdrop::contract::execute, + sg_eth_airdrop::rekt_airdrop::contract::instantiate, + sg_eth_airdrop::rekt_airdrop::query::query, ) - .with_reply(sg_eth_airdrop::reply::reply); + .with_reply(sg_eth_airdrop::rekt_airdrop::reply::reply); Box::new(contract) } diff --git a/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs b/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs index 7f6674cf8..06c200112 100644 --- a/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs +++ b/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs @@ -54,7 +54,7 @@ pub fn execute_airdrop_claim( target_wallet: Addr, airdrop_contract: Addr, ) { - let claim_message = sg_eth_airdrop::msg::ExecuteMsg::ClaimAirdrop { + let claim_message = sg_eth_airdrop::rekt_airdrop::msg::ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str, eth_sig: eth_sig_str, }; diff --git a/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs b/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs index 5a1a105eb..caccdd212 100644 --- a/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs +++ b/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs @@ -9,7 +9,7 @@ use cosmwasm_std::{coins, Addr}; use cw_multi_test::error::Error; use cw_multi_test::{AppResponse, BankSudo, Executor, SudoMsg}; use eyre::Result; -use sg_eth_airdrop::msg::{ExecuteMsg, InstantiateMsg}; +use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg}; use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; diff --git a/test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs b/test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs index 07a84c060..a20daa8b6 100644 --- a/test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs +++ b/test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs @@ -3,7 +3,7 @@ use cosmwasm_std::{ to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, }; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::error::ContractError; +use sg_eth_airdrop::rekt_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use vending_factory::msg::VendingMinterCreateMsg; use vending_minter::msg::{ExecuteMsg, QueryMsg}; diff --git a/test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs b/test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs index 28581e8a0..845fb96f7 100644 --- a/test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs +++ b/test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs @@ -1,7 +1,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::error::ContractError; +use sg_eth_airdrop::rekt_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use sg_whitelist::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; diff --git a/test-suite/src/sg_eth_airdrop/tests/test_claim.rs b/test-suite/src/sg_eth_airdrop/tests/test_claim.rs index 4c93c5432..26572013a 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_claim.rs +++ b/test-suite/src/sg_eth_airdrop/tests/test_claim.rs @@ -7,7 +7,7 @@ use crate::sg_eth_airdrop::setup::setup_signatures::{ use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; use async_std::task; use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; -use sg_eth_airdrop::msg::{ExecuteMsg, QueryMsg}; +use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, QueryMsg}; use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; @@ -22,7 +22,7 @@ use crate::sg_eth_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, }; -use sg_eth_airdrop::contract::INSTANTIATION_FEE; +use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minter_addr: Addr) { let query_msg = QueryMsg::GetMinter {}; diff --git a/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs index 808287f80..3bf3c7621 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs @@ -12,11 +12,11 @@ use crate::sg_eth_airdrop::setup::execute_msg::instantiate_contract; use crate::sg_eth_airdrop::setup::setup_signatures::{get_msg_plaintext, get_wallet_and_sig}; use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::msg::QueryMsg; +use sg_eth_airdrop::rekt_airdrop::msg::QueryMsg; use sg_std::GENESIS_MINT_START_TIME; extern crate whitelist_immutable; use crate::common_setup::templates::vending_minter_template; -use sg_eth_airdrop::contract::INSTANTIATION_FEE; +use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; #[test] fn test_set_minter_contract_success() { diff --git a/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs index 4d64e992e..a9855aee8 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs @@ -8,8 +8,8 @@ use crate::sg_eth_airdrop::setup::execute_msg::instantiate_contract; use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::contract::INSTANTIATION_FEE; -use sg_eth_airdrop::msg::QueryMsg; +use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; +use sg_eth_airdrop::rekt_airdrop::msg::QueryMsg; use whitelist_immutable::helpers::WhitelistImmutableContract; #[test] @@ -20,7 +20,7 @@ fn test_instantiate_with_addresses() { "addr3".to_string(), ]; - let mut app = custom_mock_app(); + let mut app = { custom_mock_app }(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); From 15b318a2698f4ccbf4d6b608250653f8350bf143 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 13:11:03 -0800 Subject: [PATCH 02/42] fix lint --- test-suite/src/whitelist_merkletree/tests/integration_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-suite/src/whitelist_merkletree/tests/integration_tests.rs b/test-suite/src/whitelist_merkletree/tests/integration_tests.rs index 6f846f256..0d503c99f 100644 --- a/test-suite/src/whitelist_merkletree/tests/integration_tests.rs +++ b/test-suite/src/whitelist_merkletree/tests/integration_tests.rs @@ -90,7 +90,7 @@ mod tests { .query_wasm_smart( wl_addr, &QueryMsg::HasMember { - member: addr_to_check.to_string(), + member: addr_to_check, proof_hashes, }, ) From a654c78b3c73207317b3256a1498a03536b99f18 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 13:14:02 -0800 Subject: [PATCH 03/42] fix lint --- contracts/sg-eth-airdrop/src/dydx_airdrop.rs | 1 + contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs | 1 + 2 files changed, 2 insertions(+) create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop.rs index e69de29bb..2943dbb50 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop.rs @@ -0,0 +1 @@ +pub mod contract; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs new file mode 100644 index 000000000..a90b675b1 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs @@ -0,0 +1 @@ +//to be written From 65cd73513e766495011d8ab03b25659eb3100242 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 14:03:32 -0800 Subject: [PATCH 04/42] copy files in parallel for dydx airdrop --- contracts/sg-eth-airdrop/src/dydx_airdrop.rs | 7 + .../src/dydx_airdrop/claim_airdrop.rs | 176 ++++++ .../src/dydx_airdrop/contract.rs | 148 ++++- .../sg-eth-airdrop/src/dydx_airdrop/error.rs | 54 ++ .../sg-eth-airdrop/src/dydx_airdrop/msg.rs | 37 ++ .../sg-eth-airdrop/src/dydx_airdrop/query.rs | 53 ++ .../sg-eth-airdrop/src/dydx_airdrop/reply.rs | 37 ++ .../sg-eth-airdrop/src/dydx_airdrop/state.rs | 16 + .../src/rekt_airdrop/testing.rs | 6 - test-suite/src/sg_eth_airdrop/constants.rs | 4 +- .../sg_eth_airdrop/constants/dydx_airdrop.rs | 2 + .../{ => dydx_airdrop}/claim_constants.rs | 0 .../collection_constants.rs | 0 .../sg_eth_airdrop/constants/rekt_airdrop.rs | 2 + .../constants/rekt_airdrop/claim_constants.rs | 7 + .../rekt_airdrop/collection_constants.rs | 5 + test-suite/src/sg_eth_airdrop/setup.rs | 9 +- .../src/sg_eth_airdrop/setup/dydx_airdrop.rs | 7 + .../collection_whitelist_helpers.rs | 78 +++ .../configure_mock_minter.rs | 6 +- .../setup/dydx_airdrop/execute_msg.rs | 77 +++ .../dydx_airdrop/mock_minter_contract.rs | 72 +++ .../dydx_airdrop/mock_whitelist_contract.rs | 45 ++ .../{ => dydx_airdrop}/setup_signatures.rs | 2 +- .../setup/{ => dydx_airdrop}/test_msgs.rs | 0 .../src/sg_eth_airdrop/setup/rekt_airdrop.rs | 7 + .../collection_whitelist_helpers.rs | 10 +- .../rekt_airdrop/configure_mock_minter.rs | 53 ++ .../setup/{ => rekt_airdrop}/execute_msg.rs | 6 +- .../mock_minter_contract.rs | 0 .../mock_whitelist_contract.rs | 0 .../setup/rekt_airdrop/setup_signatures.rs | 32 + .../setup/rekt_airdrop/test_msgs.rs | 13 + test-suite/src/sg_eth_airdrop/tests.rs | 5 +- .../src/sg_eth_airdrop/tests/dydx_airdrop.rs | 3 + .../tests/dydx_airdrop/test_claim.rs | 595 ++++++++++++++++++ .../dydx_airdrop/test_collection_whitelist.rs | 91 +++ .../dydx_airdrop/test_immutable_whitelist.rs | 187 ++++++ .../src/sg_eth_airdrop/tests/rekt_airdrop.rs | 3 + .../tests/{ => rekt_airdrop}/test_claim.rs | 12 +- .../test_collection_whitelist.rs | 16 +- .../test_immutable_whitelist.rs | 10 +- 42 files changed, 1847 insertions(+), 46 deletions(-) create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs create mode 100644 contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs delete mode 100644 contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs create mode 100644 test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs rename test-suite/src/sg_eth_airdrop/constants/{ => dydx_airdrop}/claim_constants.rs (100%) rename test-suite/src/sg_eth_airdrop/constants/{ => dydx_airdrop}/collection_constants.rs (100%) create mode 100644 test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs create mode 100644 test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs create mode 100644 test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs create mode 100644 test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs create mode 100644 test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs rename test-suite/src/sg_eth_airdrop/setup/{ => dydx_airdrop}/configure_mock_minter.rs (88%) create mode 100644 test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs create mode 100644 test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs create mode 100644 test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs rename test-suite/src/sg_eth_airdrop/setup/{ => dydx_airdrop}/setup_signatures.rs (91%) rename test-suite/src/sg_eth_airdrop/setup/{ => dydx_airdrop}/test_msgs.rs (100%) create mode 100644 test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs rename test-suite/src/sg_eth_airdrop/setup/{ => rekt_airdrop}/collection_whitelist_helpers.rs (87%) create mode 100644 test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs rename test-suite/src/sg_eth_airdrop/setup/{ => rekt_airdrop}/execute_msg.rs (90%) rename test-suite/src/sg_eth_airdrop/setup/{ => rekt_airdrop}/mock_minter_contract.rs (100%) rename test-suite/src/sg_eth_airdrop/setup/{ => rekt_airdrop}/mock_whitelist_contract.rs (100%) create mode 100644 test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs create mode 100644 test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs create mode 100644 test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs create mode 100644 test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs create mode 100644 test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs create mode 100644 test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs create mode 100644 test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs rename test-suite/src/sg_eth_airdrop/tests/{ => rekt_airdrop}/test_claim.rs (97%) rename test-suite/src/sg_eth_airdrop/tests/{ => rekt_airdrop}/test_collection_whitelist.rs (86%) rename test-suite/src/sg_eth_airdrop/tests/{ => rekt_airdrop}/test_immutable_whitelist.rs (93%) diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop.rs index 2943dbb50..25e7b3286 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop.rs @@ -1 +1,8 @@ pub mod contract; +pub mod error; +pub mod msg; +pub mod query; +pub mod reply; +pub mod state; +pub use crate::dydx_airdrop::error::ContractError; +mod claim_airdrop; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs new file mode 100644 index 000000000..f7f1c9700 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs @@ -0,0 +1,176 @@ +use crate::dydx_airdrop::query::query_collection_whitelist; +use crate::dydx_airdrop::state::ADDRS_TO_MINT_COUNT; +use crate::dydx_airdrop::{state::CONFIG, ContractError}; +use build_messages::claim_and_whitelist_add; +use cosmwasm_std::DepsMut; +use cosmwasm_std::{coins, Addr, BankMsg, StdResult}; +use cosmwasm_std::{Env, MessageInfo}; +use sg_std::Response; +use sg_std::{CosmosMsg, SubMsg}; +use sg_whitelist::msg::ExecuteMsg as CollectionWhitelistExecuteMsg; +use sg_whitelist::{helpers::interface::CollectionWhitelistContract, msg::AddMembersMsg}; +use validation::validate_claim; + +pub fn claim_airdrop( + deps: DepsMut, + info: MessageInfo, + _env: Env, + eth_address: String, + eth_sig: String, +) -> Result { + let config = CONFIG.load(deps.storage)?; + validate_claim( + &deps, + info.clone(), + eth_address.clone(), + eth_sig, + config.clone(), + )?; + let res = claim_and_whitelist_add(&deps, info, config.airdrop_amount)?; + increment_local_mint_count_for_address(deps, eth_address)?; + + Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) +} + +pub fn increment_local_mint_count_for_address( + deps: DepsMut, + eth_address: String, +) -> Result { + let mint_count_for_address = ADDRS_TO_MINT_COUNT + .load(deps.storage, ð_address) + .unwrap_or(0); + ADDRS_TO_MINT_COUNT.save(deps.storage, ð_address, &(mint_count_for_address + 1))?; + + Ok(Response::new()) +} + +mod build_messages { + use super::*; + use sg_std::NATIVE_DENOM; + + pub fn claim_and_whitelist_add( + deps: &DepsMut, + info: MessageInfo, + airdrop_amount: u128, + ) -> Result { + let mut res = Response::new(); + let bank_msg = SubMsg::new(BankMsg::Send { + to_address: info.sender.to_string(), + amount: coins(airdrop_amount, NATIVE_DENOM), + }); + res = res.add_submessage(bank_msg); + let collection_whitelist = query_collection_whitelist(deps)?; + let res = res.add_message(add_member_to_collection_whitelist( + deps, + info.sender, + collection_whitelist, + )?); + Ok(res) + } + + fn add_member_to_collection_whitelist( + deps: &DepsMut, + wallet_address: Addr, + collection_whitelist: String, + ) -> StdResult { + let inner_msg = AddMembersMsg { + to_add: vec![wallet_address.to_string()], + }; + let execute_msg = CollectionWhitelistExecuteMsg::AddMembers(inner_msg); + CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?) + .call(execute_msg) + } +} + +mod validation { + use super::*; + use cosmwasm_std::StdError; + use ethereum_verify::verify_ethereum_text; + + use crate::{ + dydx_airdrop::query::{query_airdrop_is_eligible, query_per_address_limit}, + dydx_airdrop::state::Config, + }; + + pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { + str::replace( + &config.claim_msg_plaintext, + "{wallet}", + info.sender.as_ref(), + ) + } + + pub fn validate_claim( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, + eth_sig: String, + config: Config, + ) -> Result<(), ContractError> { + validate_is_eligible(deps, eth_address.clone())?; + validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; + validate_mints_remaining(deps, ð_address)?; + Ok(()) + } + + fn validate_is_eligible(deps: &DepsMut, eth_address: String) -> Result<(), ContractError> { + let eligible = query_airdrop_is_eligible(deps.as_ref(), eth_address.clone())?; + match eligible { + true => Ok(()), + false => Err(ContractError::AddressNotEligible { + address: eth_address, + }), + } + } + + fn validate_eth_sig( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, + eth_sig: String, + config: Config, + ) -> Result<(), ContractError> { + let valid_eth_sig = + validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; + match valid_eth_sig { + true => Ok(()), + false => Err(ContractError::AddressNotEligible { + address: eth_address, + }), + } + } + + pub fn validate_mints_remaining( + deps: &DepsMut, + eth_address: &str, + ) -> Result<(), ContractError> { + let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); + let mint_count = mint_count.unwrap_or(0); + let per_address_limit = query_per_address_limit(&deps.as_ref())?; + if mint_count < per_address_limit { + Ok(()) + } else { + Err(ContractError::MintCountReached { + address: eth_address.to_string(), + }) + } + } + + pub fn validate_ethereum_text( + deps: &DepsMut, + info: MessageInfo, + config: &Config, + eth_sig: String, + eth_address: String, + ) -> StdResult { + let plaintext_msg = compute_plaintext_msg(config, info); + match hex::decode(eth_sig.clone()) { + Ok(eth_sig_hex) => { + verify_ethereum_text(deps.as_ref(), &plaintext_msg, ð_sig_hex, ð_address) + } + Err(_) => Err(StdError::InvalidHex { + msg: format!("Could not decode {eth_sig}"), + }), + } + } +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs index a90b675b1..f1c434057 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs @@ -1 +1,147 @@ -//to be written +use crate::dydx_airdrop::claim_airdrop::claim_airdrop; +#[cfg(not(feature = "library"))] +use crate::dydx_airdrop::error::ContractError; +use crate::dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg}; +use crate::dydx_airdrop::state::CONFIG; + +use cosmwasm_std::entry_point; +use cosmwasm_std::{DepsMut, Env, MessageInfo}; +use cw2::set_contract_version; +use sg1::fair_burn; +use sg_std::Response; + +use build_message::{state_config, whitelist_instantiate}; +use validation::validate_instantiation_params; + +const CONTRACT_NAME: &str = "crates.io:sg-eth-airdrop"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const INSTANTIATION_FEE: u128 = 100_000_000; // 100 STARS + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + validate_instantiation_params(info.clone(), msg.clone())?; + let mut res = Response::new(); + fair_burn(INSTANTIATION_FEE, None, &mut res); + let cfg = state_config(deps.as_ref(), info.clone(), msg.clone())?; + CONFIG.save(deps.storage, &cfg)?; + Ok(res + .add_attribute("action", "instantiate") + .add_attribute("contract_name", CONTRACT_NAME) + .add_attribute("contract_version", CONTRACT_VERSION) + .add_attribute("sender", info.sender) + .add_submessage(whitelist_instantiate(env, msg)?)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::ClaimAirdrop { + eth_address, + eth_sig, + } => claim_airdrop(deps, info, _env, eth_address, eth_sig), + } +} + +mod build_message { + use super::*; + use crate::dydx_airdrop::state::Config; + use cosmwasm_std::{to_binary, Deps, WasmMsg}; + use sg_std::{StargazeMsgWrapper, SubMsg}; + use validation::validate_airdrop_amount; + use whitelist_immutable::msg::InstantiateMsg as WGInstantiateMsg; + + pub const GENERIC_WHITELIST_LABEL: &str = "Generic Whitelist for Airdrop"; + pub const INIT_WHITELIST_REPLY_ID: u64 = 1; + + pub fn whitelist_instantiate( + env: Env, + msg: InstantiateMsg, + ) -> Result, ContractError> { + let whitelist_instantiate_msg = WGInstantiateMsg { + addresses: msg.addresses, + mint_discount_bps: Some(0), + per_address_limit: msg.per_address_limit, + }; + let wasm_msg = WasmMsg::Instantiate { + code_id: msg.whitelist_code_id, + admin: Some(env.contract.address.to_string()), + funds: vec![], + label: GENERIC_WHITELIST_LABEL.to_string(), + msg: to_binary(&whitelist_instantiate_msg)?, + }; + Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) + } + + pub fn state_config( + deps: Deps, + info: MessageInfo, + msg: InstantiateMsg, + ) -> Result { + Ok(Config { + admin: info.sender, + claim_msg_plaintext: msg.clone().claim_msg_plaintext, + airdrop_amount: validate_airdrop_amount(msg.airdrop_amount)?, + whitelist_address: None, + minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, + }) + } +} + +mod validation { + use super::*; + use cosmwasm_std::Uint128; + use cw_utils::must_pay; + use sg_std::NATIVE_DENOM; + + const MIN_AIRDROP: u128 = 10_000_000; // 10 STARS + const MAX_AIRDROP: u128 = 100_000_000_000_000; // 100 million STARS + + pub fn validate_instantiation_params( + info: MessageInfo, + msg: InstantiateMsg, + ) -> Result<(), ContractError> { + validate_airdrop_amount(msg.airdrop_amount)?; + validate_plaintext_msg(msg.claim_msg_plaintext)?; + validate_instantiate_funds(info)?; + Ok(()) + } + + pub fn validate_instantiate_funds(info: MessageInfo) -> Result<(), ContractError> { + let amount = must_pay(&info, NATIVE_DENOM)?; + if amount < Uint128::from(INSTANTIATION_FEE) { + return Err(ContractError::InsufficientFundsInstantiate {}); + }; + Ok(()) + } + + pub fn validate_airdrop_amount(airdrop_amount: u128) -> Result { + if airdrop_amount < MIN_AIRDROP { + return Err(ContractError::AirdropTooSmall {}); + }; + if airdrop_amount > MAX_AIRDROP { + return Err(ContractError::AirdropTooBig {}); + }; + Ok(airdrop_amount) + } + + pub fn validate_plaintext_msg(plaintext_msg: String) -> Result<(), ContractError> { + if !plaintext_msg.contains("{wallet}") { + return Err(ContractError::PlaintextMsgNoWallet {}); + } + if plaintext_msg.len() > 1000 { + return Err(ContractError::PlaintextTooLong {}); + } + Ok(()) + } +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs new file mode 100644 index 000000000..67e7b7a64 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs @@ -0,0 +1,54 @@ +use cosmwasm_std::{Addr, StdError}; +use cw_utils::{self, PaymentError}; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + PaymentError(#[from] PaymentError), + + #[error("Contract has no funds")] + NoFunds {}, + + #[error("Insufficient Funds for Instantiate")] + InsufficientFundsInstantiate {}, + + #[error("Airdrop Amount Too Small")] + AirdropTooSmall {}, + + #[error("Airdrop Amount Too Big")] + AirdropTooBig {}, + + #[error("Invalid reply ID")] + InvalidReplyID {}, + + #[error("Unauthorized admin, sender is {sender}")] + Unauthorized { sender: Addr }, + + #[error("Reply error")] + ReplyOnSuccess {}, + + #[error("Whitelist contract has not been set")] + WhitelistContractNotSet {}, + + #[error("Minter already set")] + MinterAlreadySet {}, + + #[error("Address {address} is not eligible")] + AddressNotEligible { address: String }, + + #[error("Address {address} has already claimed all available mints")] + MintCountReached { address: String }, + + #[error("Collection Whitelist on Minter contract has not been set")] + CollectionWhitelistMinterNotSet {}, + + #[error("Plaintext message must contain `{{wallet}}` string")] + PlaintextMsgNoWallet {}, + + #[error("Plaintext message is too long")] + PlaintextTooLong {}, +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs new file mode 100644 index 000000000..cbf5ccdee --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs @@ -0,0 +1,37 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Addr; + +#[cw_serde] +pub struct InstantiateMsg { + pub admin: Addr, + pub claim_msg_plaintext: String, + pub airdrop_amount: u128, + pub addresses: Vec, + pub whitelist_code_id: u64, + pub minter_address: Addr, + pub per_address_limit: u32, +} + +#[cw_serde] +pub struct AirdropClaimResponse { + result: bool, + amount: u32, + minter_page: String, +} + +#[cw_serde] +pub enum ExecuteMsg { + ClaimAirdrop { + eth_address: String, + eth_sig: String, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(bool)] + AirdropEligible { eth_address: String }, + #[returns(Addr)] + GetMinter {}, +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs new file mode 100644 index 000000000..d7b06a8df --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs @@ -0,0 +1,53 @@ +use crate::dydx_airdrop::{msg::QueryMsg, state::CONFIG, ContractError}; +use cosmwasm_std::{entry_point, to_binary, Binary}; +use cosmwasm_std::{Addr, Env}; +use cosmwasm_std::{Deps, DepsMut, StdResult}; +use vending_minter::helpers::MinterContract; +use whitelist_immutable::helpers::WhitelistImmutableContract; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::AirdropEligible { eth_address } => { + to_binary(&query_airdrop_is_eligible(deps, eth_address)?) + } + QueryMsg::GetMinter {} => to_binary(&query_minter(deps)?), + } +} + +fn query_minter(deps: Deps) -> StdResult { + let config = CONFIG.load(deps.storage)?; + Ok(config.minter_address) +} + +pub fn query_airdrop_is_eligible(deps: Deps, eth_address: String) -> StdResult { + let config = CONFIG.load(deps.storage)?; + match config.whitelist_address { + Some(address) => WhitelistImmutableContract(deps.api.addr_validate(&address)?) + .includes(&deps.querier, eth_address), + None => Err(cosmwasm_std::StdError::NotFound { + kind: "Whitelist Contract".to_string(), + }), + } +} + +pub fn query_collection_whitelist(deps: &DepsMut) -> Result { + let config = CONFIG.load(deps.storage)?; + let minter_addr = config.minter_address; + let config = MinterContract(minter_addr).config(&deps.querier)?; + match config.whitelist { + Some(whitelist) => Ok(whitelist), + None => Err(ContractError::CollectionWhitelistMinterNotSet {}), + } +} + +pub fn query_per_address_limit(deps: &Deps) -> StdResult { + let config = CONFIG.load(deps.storage)?; + match config.whitelist_address { + Some(address) => WhitelistImmutableContract(deps.api.addr_validate(&address)?) + .per_address_limit(&deps.querier), + None => Err(cosmwasm_std::StdError::NotFound { + kind: "Whitelist Contract".to_string(), + }), + } +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs new file mode 100644 index 000000000..d82588068 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs @@ -0,0 +1,37 @@ +#[cfg(not(feature = "library"))] +use crate::dydx_airdrop::error::ContractError; +use crate::dydx_airdrop::state::CONFIG; +use cosmwasm_std::entry_point; +use cosmwasm_std::{DepsMut, Env, Reply}; +use cw_utils::{parse_reply_instantiate_data, MsgInstantiateContractResponse, ParseReplyError}; +use sg_std::Response; + +const INIT_WHITELIST_REPLY_ID: u64 = 1; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { + if msg.id != INIT_WHITELIST_REPLY_ID { + return Err(ContractError::InvalidReplyID {}); + } + let reply = parse_reply_instantiate_data(msg); + match_reply(deps, reply) +} + +fn match_reply( + deps: DepsMut, + reply: Result, +) -> Result { + match reply { + Ok(res) => { + let whitelist_address = &res.contract_address; + let mut config = CONFIG.load(deps.storage)?; + config.whitelist_address = Some(whitelist_address.to_string()); + CONFIG.save(deps.storage, &config)?; + + Ok(Response::default() + .add_attribute("action", "init_whitelist_reply") + .add_attribute("whitelist_address", whitelist_address)) + } + Err(_) => Err(ContractError::ReplyOnSuccess {}), + } +} diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs b/contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs new file mode 100644 index 000000000..cefb96d81 --- /dev/null +++ b/contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs @@ -0,0 +1,16 @@ +use cosmwasm_std::Addr; +use cw_storage_plus::{Item, Map}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, Debug)] +pub struct Config { + pub admin: Addr, + pub claim_msg_plaintext: String, + pub airdrop_amount: u128, + pub whitelist_address: Option, + pub minter_address: Addr, +} + +pub const CONFIG: Item = Item::new("cfg"); +pub const ADDRS_TO_MINT_COUNT: Map<&str, u32> = Map::new("amc"); diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs b/contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs deleted file mode 100644 index 2103f40ee..000000000 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop/testing.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[cfg(test)] -mod constants; -#[cfg(test)] -mod setup; -#[cfg(test)] -mod tests; diff --git a/test-suite/src/sg_eth_airdrop/constants.rs b/test-suite/src/sg_eth_airdrop/constants.rs index 9d2841356..3abd8698a 100644 --- a/test-suite/src/sg_eth_airdrop/constants.rs +++ b/test-suite/src/sg_eth_airdrop/constants.rs @@ -1,2 +1,2 @@ -pub mod claim_constants; -pub mod collection_constants; +pub mod dydx_airdrop; +pub mod rekt_airdrop; diff --git a/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs b/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs new file mode 100644 index 000000000..9d2841356 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs @@ -0,0 +1,2 @@ +pub mod claim_constants; +pub mod collection_constants; diff --git a/test-suite/src/sg_eth_airdrop/constants/claim_constants.rs b/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/claim_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/claim_constants.rs rename to test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/claim_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/collection_constants.rs b/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/collection_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/collection_constants.rs rename to test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/collection_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs new file mode 100644 index 000000000..9d2841356 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs @@ -0,0 +1,2 @@ +pub mod claim_constants; +pub mod collection_constants; diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs new file mode 100644 index 000000000..674d66784 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs @@ -0,0 +1,7 @@ +pub const OWNER: &str = "admin0001"; +pub const MOCK_AIRDROP_ADDR_STR: &str = "contract3"; +pub const MOCK_MINTER_ADDR_STR: &str = "contract1"; +pub const STARGAZE_WALLET_01: &str = "0xstargaze_wallet_01"; +pub const STARGAZE_WALLET_02: &str = "0xstargaze_wallet_02"; +pub const CONFIG_PLAINTEXT: &str = "My Stargaze address is {wallet} and I want a Winter Pal."; +pub const NATIVE_DENOM: &str = "ustars"; diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs new file mode 100644 index 000000000..1c29cc2d4 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs @@ -0,0 +1,5 @@ +pub const CREATION_FEE: u128 = 5_000_000_000; +pub const MINT_PRICE: u128 = 100_000_000; +pub const WHITELIST_AMOUNT: u128 = 66_000_000; + +pub const AIRDROP_ADDR_STR: &str = "contract4"; diff --git a/test-suite/src/sg_eth_airdrop/setup.rs b/test-suite/src/sg_eth_airdrop/setup.rs index fc6734421..3abd8698a 100644 --- a/test-suite/src/sg_eth_airdrop/setup.rs +++ b/test-suite/src/sg_eth_airdrop/setup.rs @@ -1,7 +1,2 @@ -pub mod collection_whitelist_helpers; -pub mod configure_mock_minter; -pub mod execute_msg; -pub mod mock_minter_contract; -pub mod mock_whitelist_contract; -pub mod setup_signatures; -pub mod test_msgs; +pub mod dydx_airdrop; +pub mod rekt_airdrop; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs new file mode 100644 index 000000000..fc6734421 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs @@ -0,0 +1,7 @@ +pub mod collection_whitelist_helpers; +pub mod configure_mock_minter; +pub mod execute_msg; +pub mod mock_minter_contract; +pub mod mock_whitelist_contract; +pub mod setup_signatures; +pub mod test_msgs; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs new file mode 100644 index 000000000..ca0147aff --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs @@ -0,0 +1,78 @@ +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ + NATIVE_DENOM, STARGAZE_WALLET_01, +}; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::{ + MINT_PRICE, WHITELIST_AMOUNT, +}; + +use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::execute_contract_with_msg; +use cosmwasm_std::{coins, Addr}; +use cw_multi_test::{BankSudo, Executor, SudoMsg}; +use sg_multi_test::StargazeApp; + +extern crate whitelist_immutable; + +pub fn update_admin_for_whitelist( + app: &mut StargazeApp, + sender: Addr, + target_admin: Addr, + target_contract: Addr, +) { + // add airdrop contract as admin on whitelist + let update_admin_message = sg_whitelist::msg::ExecuteMsg::UpdateAdmins { + admins: vec![target_admin.to_string()], + }; + let _ = app.execute_contract(sender, target_contract, &update_admin_message, &[]); +} + +pub fn send_funds_to_address(app: &mut StargazeApp, target_address_str: &str, amount: u128) { + app.sudo(SudoMsg::Bank({ + BankSudo::Mint { + to_address: target_address_str.to_string(), + amount: coins(amount, NATIVE_DENOM), + } + })) + .map_err(|err| println!("{err:?}")) + .ok(); +} + +pub fn execute_mint_fail_not_on_whitelist(app: &mut StargazeApp, minter_addr: Addr) { + //before mintlist add, fail + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + let mint_msg = vending_minter::msg::ExecuteMsg::Mint {}; + let res = app.execute_contract( + stargaze_wallet_01, + minter_addr, + &mint_msg, + &coins(MINT_PRICE, NATIVE_DENOM), + ); + + let expected_error = format!("address not on whitelist: {STARGAZE_WALLET_01}"); + assert_eq!(res.unwrap_err().root_cause().to_string(), expected_error); +} + +pub fn execute_airdrop_claim( + app: &mut StargazeApp, + eth_addr_str: String, + eth_sig_str: String, + target_wallet: Addr, + airdrop_contract: Addr, +) { + let claim_message = sg_eth_airdrop::dydx_airdrop::msg::ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str, + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg(claim_message, app, target_wallet, airdrop_contract).unwrap(); +} + +pub fn execute_mint_success(app: &mut StargazeApp, sender: Addr, minter_addr: Addr) { + //execute the mint + let mint_msg = vending_minter::msg::ExecuteMsg::Mint {}; + let res = app.execute_contract( + sender, + minter_addr, + &mint_msg, + &coins(WHITELIST_AMOUNT, NATIVE_DENOM), + ); + assert!(res.is_ok()) +} diff --git a/test-suite/src/sg_eth_airdrop/setup/configure_mock_minter.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs similarity index 88% rename from test-suite/src/sg_eth_airdrop/setup/configure_mock_minter.rs rename to test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs index 516c9913f..cfc9f32b9 100644 --- a/test-suite/src/sg_eth_airdrop/setup/configure_mock_minter.rs +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs @@ -5,8 +5,8 @@ use crate::common_setup::contract_boxes::contract_vending_factory; use crate::common_setup::setup_minter::vending_minter::mock_params::{ mock_create_minter, mock_params, }; -use crate::sg_eth_airdrop::constants::collection_constants::CREATION_FEE; -use crate::sg_eth_airdrop::setup::mock_minter_contract::mock_minter; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::CREATION_FEE; +use crate::sg_eth_airdrop::setup::dydx_airdrop::mock_minter_contract::mock_minter; use cosmwasm_std::{coins, Addr, Timestamp}; use cw_multi_test::Executor; use sg2::msg::Sg2ExecuteMsg; @@ -14,7 +14,7 @@ use sg2::tests::mock_collection_params_1; use sg_multi_test::StargazeApp; use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use crate::sg_eth_airdrop::setup::mock_whitelist_contract::mock_whitelist; +use crate::sg_eth_airdrop::setup::dydx_airdrop::mock_whitelist_contract::mock_whitelist; fn configure_mock_minter(app: &mut StargazeApp, creator: Addr) { let minter_code_id = app.store_code(mock_minter()); diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs new file mode 100644 index 000000000..ba5e35a16 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs @@ -0,0 +1,77 @@ +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::OWNER; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::{ + common_setup::contract_boxes::{contract_eth_airdrop, contract_whitelist_immutable}, + sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams, +}; +use anyhow::Error as anyhow_error; +use cosmwasm_std::{coins, Addr}; +use cw_multi_test::error::Error; +use cw_multi_test::{AppResponse, BankSudo, Executor, SudoMsg}; +use eyre::Result; +use sg_eth_airdrop::dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg}; +use sg_multi_test::StargazeApp; +use sg_std::NATIVE_DENOM; + +pub fn instantiate_contract(params: InstantiateParams) -> Result { + let addresses = params.addresses; + let minter_address = params.minter_address; + let admin_account = params.admin_account; + let funds_amount = params.funds_amount; + let per_address_limit = params.per_address_limit; + let claim_msg_plaintext = params.claim_msg_plaintext; + params + .app + .sudo(SudoMsg::Bank({ + BankSudo::Mint { + to_address: admin_account.to_string(), + amount: coins(params.funds_amount, NATIVE_DENOM), + } + })) + .map_err(|err| println!("{err:?}")) + .ok(); + + let sg_eth_id = params.app.store_code(contract_eth_airdrop()); + let whitelist_code_id = params.app.store_code(contract_whitelist_immutable()); + assert_eq!(sg_eth_id, params.expected_airdrop_contract_id); + + let msg: InstantiateMsg = InstantiateMsg { + admin: Addr::unchecked(OWNER), + claim_msg_plaintext, + airdrop_amount: WHITELIST_AMOUNT, + addresses, + whitelist_code_id, + minter_address, + per_address_limit, + }; + params.app.instantiate_contract( + sg_eth_id, + Addr::unchecked(admin_account.clone()), + &msg, + &coins(funds_amount, NATIVE_DENOM), + "sg-eg-airdrop", + Some(Addr::unchecked(admin_account).to_string()), + ) +} + +pub fn execute_contract_with_msg( + msg: ExecuteMsg, + app: &mut StargazeApp, + user: Addr, + target_address: Addr, +) -> Result { + let result = app.execute_contract(user, target_address, &msg, &[]); + Ok(result.unwrap()) +} + +pub fn execute_contract_error_with_msg( + msg: ExecuteMsg, + app: &mut StargazeApp, + user: Addr, + target_address: Addr, +) -> String { + let result = app + .execute_contract(user, target_address, &msg, &[]) + .unwrap_err(); + result.root_cause().to_string() +} diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs new file mode 100644 index 000000000..a43d85d22 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs @@ -0,0 +1,72 @@ +use cosmwasm_std::entry_point; +use cosmwasm_std::{ + to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, +}; +use cw_multi_test::{Contract, ContractWrapper}; +use sg_eth_airdrop::dydx_airdrop::error::ContractError; +use sg_std::{Response, StargazeMsgWrapper}; +use vending_factory::msg::VendingMinterCreateMsg; +use vending_minter::msg::{ExecuteMsg, QueryMsg}; + +use cosmwasm_schema::cw_serde; +#[cw_serde] +pub struct ConfigResponse { + pub admin: String, + pub base_token_uri: String, + pub num_tokens: u32, + pub per_address_limit: u32, + pub sg721_address: String, + pub sg721_code_id: u64, + pub start_time: Timestamp, + pub mint_price: Coin, + pub whitelist: Option, + pub factory: String, +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: VendingMinterCreateMsg, +) -> Result { + let res = Response::new(); + Ok(res) +} + +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: ExecuteMsg, +) -> Result { + Err(ContractError::CollectionWhitelistMinterNotSet {}) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Config {} => to_binary(&query_config()), + _ => to_binary("invalid"), + } +} + +fn query_config() -> ConfigResponse { + ConfigResponse { + admin: "some_admin".to_string(), + whitelist: Some("contract2".to_string()), + base_token_uri: "some_uri".to_string(), + num_tokens: 5, + per_address_limit: 5, + sg721_address: "some_sg721_address".to_string(), + sg721_code_id: 4, + start_time: Timestamp::from_seconds(30), + mint_price: Coin::new(1000, "ustars"), + factory: "some_factory".to_string(), + } +} + +pub fn mock_minter() -> Box> { + let contract = ContractWrapper::new(execute, instantiate, query); + Box::new(contract) +} diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs new file mode 100644 index 000000000..4e20f20ec --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs @@ -0,0 +1,45 @@ +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; +use cw_multi_test::{Contract, ContractWrapper}; +use sg_eth_airdrop::dydx_airdrop::error::ContractError; +use sg_std::{Response, StargazeMsgWrapper}; +use sg_whitelist::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + mut _msg: InstantiateMsg, +) -> Result { + let res = Response::new(); + Ok(res) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::AddMembers(_) => execute_add_members(), + _ => Err(ContractError::InvalidReplyID {}), + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult { + to_binary("mock") +} + +fn execute_add_members() -> Result { + let res = Response::new(); + Ok(res) +} + +pub fn mock_whitelist() -> Box> { + let contract = ContractWrapper::new(execute, instantiate, query); + Box::new(contract) +} diff --git a/test-suite/src/sg_eth_airdrop/setup/setup_signatures.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs similarity index 91% rename from test-suite/src/sg_eth_airdrop/setup/setup_signatures.rs rename to test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs index ea639bf0a..5e8c8f771 100644 --- a/test-suite/src/sg_eth_airdrop/setup/setup_signatures.rs +++ b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs @@ -1,4 +1,4 @@ -use crate::sg_eth_airdrop::constants::claim_constants::CONFIG_PLAINTEXT; +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::CONFIG_PLAINTEXT; use async_std::task; use ethers_core::{k256::ecdsa::SigningKey, rand::thread_rng, types::H160}; use ethers_signers::{LocalWallet, Signer, Wallet, WalletError}; diff --git a/test-suite/src/sg_eth_airdrop/setup/test_msgs.rs b/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/test_msgs.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/test_msgs.rs rename to test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/test_msgs.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs new file mode 100644 index 000000000..fc6734421 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs @@ -0,0 +1,7 @@ +pub mod collection_whitelist_helpers; +pub mod configure_mock_minter; +pub mod execute_msg; +pub mod mock_minter_contract; +pub mod mock_whitelist_contract; +pub mod setup_signatures; +pub mod test_msgs; diff --git a/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs similarity index 87% rename from test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs rename to test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs index 06c200112..486fe134a 100644 --- a/test-suite/src/sg_eth_airdrop/setup/collection_whitelist_helpers.rs +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs @@ -1,7 +1,11 @@ -use crate::sg_eth_airdrop::constants::claim_constants::{NATIVE_DENOM, STARGAZE_WALLET_01}; -use crate::sg_eth_airdrop::constants::collection_constants::{MINT_PRICE, WHITELIST_AMOUNT}; +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ + NATIVE_DENOM, STARGAZE_WALLET_01, +}; +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::{ + MINT_PRICE, WHITELIST_AMOUNT, +}; -use crate::sg_eth_airdrop::setup::execute_msg::execute_contract_with_msg; +use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::execute_contract_with_msg; use cosmwasm_std::{coins, Addr}; use cw_multi_test::{BankSudo, Executor, SudoMsg}; use sg_multi_test::StargazeApp; diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs new file mode 100644 index 000000000..66327e7af --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs @@ -0,0 +1,53 @@ +use crate::common_setup::setup_accounts_and_block::setup_accounts; +use crate::common_setup::setup_collection_whitelist::setup_whitelist_contract; + +use crate::common_setup::contract_boxes::contract_vending_factory; +use crate::common_setup::setup_minter::vending_minter::mock_params::{ + mock_create_minter, mock_params, +}; +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::CREATION_FEE; +use crate::sg_eth_airdrop::setup::rekt_airdrop::mock_minter_contract::mock_minter; +use cosmwasm_std::{coins, Addr, Timestamp}; +use cw_multi_test::Executor; +use sg2::msg::Sg2ExecuteMsg; +use sg2::tests::mock_collection_params_1; +use sg_multi_test::StargazeApp; +use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; + +use crate::sg_eth_airdrop::setup::rekt_airdrop::mock_whitelist_contract::mock_whitelist; + +fn configure_mock_minter(app: &mut StargazeApp, creator: Addr) { + let minter_code_id = app.store_code(mock_minter()); + + println!("minter_code_id: {minter_code_id}"); + let creation_fee = coins(CREATION_FEE, NATIVE_DENOM); + + let factory_code_id = app.store_code(contract_vending_factory()); + println!("factory_code_id: {factory_code_id}"); + + let mut params = mock_params(None); + params.code_id = minter_code_id; + + let factory_addr = app + .instantiate_contract( + factory_code_id, + creator.clone(), + &vending_factory::msg::InstantiateMsg { params }, + &[], + "factory", + None, + ) + .unwrap(); + let start_time = Timestamp::from_nanos(GENESIS_MINT_START_TIME); + let collection_params = mock_collection_params_1(Some(start_time)); + let msg = mock_create_minter(None, collection_params, None); + let msg = Sg2ExecuteMsg::CreateMinter(msg); + let res = app.execute_contract(creator, factory_addr, &msg, &creation_fee); + assert!(res.is_ok()); +} +pub fn configure_mock_minter_with_mock_whitelist(app: &mut StargazeApp) { + let (creator, _) = setup_accounts(app); + configure_mock_minter(app, creator.clone()); + let whitelist_code_id = app.store_code(mock_whitelist()); + setup_whitelist_contract(app, &creator, Some(whitelist_code_id), None); +} diff --git a/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs similarity index 90% rename from test-suite/src/sg_eth_airdrop/setup/execute_msg.rs rename to test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs index caccdd212..47a681bc5 100644 --- a/test-suite/src/sg_eth_airdrop/setup/execute_msg.rs +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs @@ -1,8 +1,8 @@ -use crate::sg_eth_airdrop::constants::claim_constants::OWNER; -use crate::sg_eth_airdrop::constants::collection_constants::WHITELIST_AMOUNT; +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::OWNER; +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; use crate::{ common_setup::contract_boxes::{contract_eth_airdrop, contract_whitelist_immutable}, - sg_eth_airdrop::setup::test_msgs::InstantiateParams, + sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams, }; use anyhow::Error as anyhow_error; use cosmwasm_std::{coins, Addr}; diff --git a/test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_minter_contract.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/mock_minter_contract.rs rename to test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_minter_contract.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_whitelist_contract.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/mock_whitelist_contract.rs rename to test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_whitelist_contract.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs new file mode 100644 index 000000000..60ec889d1 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs @@ -0,0 +1,32 @@ +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::CONFIG_PLAINTEXT; +use async_std::task; +use ethers_core::{k256::ecdsa::SigningKey, rand::thread_rng, types::H160}; +use ethers_signers::{LocalWallet, Signer, Wallet, WalletError}; + +pub async fn get_signature( + wallet: Wallet, + plaintext_msg: &str, +) -> Result { + wallet.sign_message(plaintext_msg).await +} + +pub fn get_wallet_and_sig( + claim_plaintext: String, +) -> ( + Wallet, + std::string::String, + H160, + std::string::String, +) { + let wallet = LocalWallet::new(&mut thread_rng()); + let eth_sig_str = task::block_on(get_signature(wallet.clone(), &claim_plaintext)) + .unwrap() + .to_string(); + let eth_address = wallet.address(); + let eth_addr_str = format!("{eth_address:?}"); + (wallet, eth_sig_str, eth_address, eth_addr_str) +} + +pub fn get_msg_plaintext(wallet_address: String) -> String { + str::replace(CONFIG_PLAINTEXT, "{wallet}", &wallet_address) +} diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs new file mode 100644 index 000000000..87e621357 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs @@ -0,0 +1,13 @@ +use cosmwasm_std::Addr; +use sg_multi_test::StargazeApp; + +pub struct InstantiateParams<'a> { + pub addresses: Vec, + pub funds_amount: u128, + pub expected_airdrop_contract_id: u64, + pub minter_address: Addr, + pub admin_account: Addr, + pub app: &'a mut StargazeApp, + pub per_address_limit: u32, + pub claim_msg_plaintext: String, +} diff --git a/test-suite/src/sg_eth_airdrop/tests.rs b/test-suite/src/sg_eth_airdrop/tests.rs index da3fde61c..3abd8698a 100644 --- a/test-suite/src/sg_eth_airdrop/tests.rs +++ b/test-suite/src/sg_eth_airdrop/tests.rs @@ -1,3 +1,2 @@ -mod test_claim; -mod test_collection_whitelist; -mod test_immutable_whitelist; +pub mod dydx_airdrop; +pub mod rekt_airdrop; diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs new file mode 100644 index 000000000..da3fde61c --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs @@ -0,0 +1,3 @@ +mod test_claim; +mod test_collection_whitelist; +mod test_immutable_whitelist; diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs new file mode 100644 index 000000000..58b6afeba --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs @@ -0,0 +1,595 @@ +use crate::common_setup::contract_boxes::custom_mock_app; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::sg_eth_airdrop::setup::dydx_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::sg_eth_airdrop::setup::dydx_airdrop::setup_signatures::{ + get_msg_plaintext, get_signature, get_wallet_and_sig, +}; +use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; +use async_std::task; +use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; +use sg_eth_airdrop::dydx_airdrop::msg::{ExecuteMsg, QueryMsg}; + +use ethers_core::rand::thread_rng; +use ethers_signers::{LocalWallet, Signer}; +use sg_multi_test::StargazeApp; + +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, NATIVE_DENOM, OWNER, + STARGAZE_WALLET_01, STARGAZE_WALLET_02, +}; + +use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::{ + execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, +}; + +use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; + +fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minter_addr: Addr) { + let query_msg = QueryMsg::GetMinter {}; + let result: Addr = app + .wrap() + .query_wasm_smart(airdrop_contract, &query_msg) + .unwrap(); + assert_eq!(minter_addr, result); +} + +#[test] +fn test_instantiate() { + let mut app = custom_mock_app(); + let minter_address = Addr::unchecked("contract1"); + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let params = InstantiateParams { + addresses: vec![eth_addr_str], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 1, + minter_address, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); +} + +#[test] +fn test_instantiate_plaintext_too_long() { + let long_config_plaintext: String = String::from_utf8(vec![b'X'; 1001]).unwrap() + " {wallet}"; + let mut app = custom_mock_app(); + let minter_address = Addr::unchecked("contract1"); + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let params = InstantiateParams { + addresses: vec![eth_addr_str], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 1, + minter_address, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: long_config_plaintext, + }; + let res = instantiate_contract(params).unwrap_err(); + assert_eq!( + res.root_cause().to_string(), + "Plaintext message is too long" + ); +} + +#[test] +fn test_instantiate_plaintext_missing_wallet() { + let plaintext_config_no_wallet = "This message doesn't have wallet string".to_string(); + let mut app = custom_mock_app(); + let minter_address = Addr::unchecked("contract1"); + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let params = InstantiateParams { + addresses: vec![eth_addr_str], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 1, + minter_address, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: plaintext_config_no_wallet, + }; + let res = instantiate_contract(params).unwrap_err(); + assert_eq!( + res.root_cause().to_string(), + "Plaintext message must contain `{wallet}` string" + ); +} + +#[test] +fn test_airdrop_eligible_query() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let query_msg = QueryMsg::AirdropEligible { + eth_address: eth_addr_str, + }; + let result: bool = app + .wrap() + .query_wasm_smart(airdrop_contract.clone(), &query_msg) + .unwrap(); + assert!(result); + + let query_msg = QueryMsg::AirdropEligible { + eth_address: "0x-some-fake-address".to_string(), + }; + let result: bool = app + .wrap() + .query_wasm_smart(airdrop_contract, &query_msg) + .unwrap(); + assert!(!result); +} + +#[test] +fn test_valid_eth_sig_claim() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str, + eth_sig: eth_sig_str, + }; + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + + let res = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01, + airdrop_contract.clone(), + ) + .unwrap(); + let expected_attributes = [ + Attribute { + key: "_contract_addr".to_string(), + value: airdrop_contract.to_string(), + }, + Attribute { + key: "claimed_amount".to_string(), + value: WHITELIST_AMOUNT.to_string(), + }, + ]; + assert_eq!(res.events[1].attributes, expected_attributes); +} + +#[test] +fn test_invalid_eth_sig_claim() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let (_, eth_sig_str_2, _, _) = get_wallet_and_sig(claim_plaintext.clone()); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str.clone(), + eth_sig: eth_sig_str_2, + }; + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + let res = execute_contract_error_with_msg( + claim_message, + &mut app, + stargaze_wallet_01, + airdrop_contract, + ); + assert_eq!(res, format!("Address {eth_addr_str} is not eligible")); +} + +#[test] +fn test_can_not_claim_twice() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str.clone(), + eth_sig: eth_sig_str, + }; + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + let res = execute_contract_with_msg( + claim_message.clone(), + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract.clone(), + ) + .unwrap(); + + let expected_attributes = [ + Attribute { + key: "_contract_addr".to_string(), + value: airdrop_contract.to_string(), + }, + Attribute { + key: "claimed_amount".to_string(), + value: WHITELIST_AMOUNT.to_string(), + }, + ]; + assert_eq!(res.events[1].attributes, expected_attributes); + let res = execute_contract_error_with_msg( + claim_message, + &mut app, + stargaze_wallet_01, + airdrop_contract, + ); + let expected_error = format!("Address {eth_addr_str} has already claimed all available mints"); + assert_eq!(res, expected_error); +} + +#[test] +fn test_claim_one_valid_airdrop() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str, + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract, + ) + .unwrap(); + + let balances = app.wrap().query_all_balances(stargaze_wallet_01).unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance) +} + +#[test] +fn test_claim_twice_receive_funds_once() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + let mut app = custom_mock_app(); + + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str.clone(), + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg( + claim_message.clone(), + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract.clone(), + ) + .unwrap(); + + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance); + let res = execute_contract_error_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract, + ); + let expected_error = format!("Address {eth_addr_str} has already claimed all available mints"); + assert_eq!(res, expected_error); + let balances = app.wrap().query_all_balances(stargaze_wallet_01).unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance); +} + +#[test] +fn test_ineligible_does_not_receive_funds() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let stargaze_wallet_02 = Addr::unchecked(STARGAZE_WALLET_02); + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_02.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_plaintext_2 = &get_msg_plaintext(STARGAZE_WALLET_02.to_string()); + let (_, eth_sig_str_2, _, eth_addr_str_2) = get_wallet_and_sig(claim_plaintext_2.clone()); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str_2.clone(), + eth_sig: eth_sig_str_2, + }; + let res = execute_contract_error_with_msg( + claim_message, + &mut app, + stargaze_wallet_02.clone(), + airdrop_contract, + ); + let expected_error = format!("Address {eth_addr_str_2} is not eligible"); + assert_eq!(res, expected_error); + let balances = app.wrap().query_all_balances(stargaze_wallet_02).unwrap(); + let expected_balance = []; + assert_eq!(balances, expected_balance) +} + +#[test] +fn test_one_eth_claim_two_stargaze_addresses_invalid() { + let wallet_1 = LocalWallet::new(&mut thread_rng()); + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + let stargaze_wallet_02 = Addr::unchecked(STARGAZE_WALLET_02); + + let claim_plaintext_1 = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let eth_sig_str_1 = task::block_on(get_signature(wallet_1.clone(), claim_plaintext_1)) + .unwrap() + .to_string(); + let eth_address = wallet_1.address(); + let eth_addr_str_1 = format!("{eth_address:?}"); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str_1.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + + // claim with eth address 1, stargaze wallet 1 + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str_1.clone(), + eth_sig: eth_sig_str_1, + }; + let res = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01, + airdrop_contract.clone(), + ) + .unwrap(); + + let expected_attributes = [ + Attribute { + key: "_contract_addr".to_string(), + value: airdrop_contract.to_string(), + }, + Attribute { + key: "claimed_amount".to_string(), + value: WHITELIST_AMOUNT.to_string(), + }, + ]; + assert_eq!(res.events[1].attributes, expected_attributes); + + let claim_plaintext_2 = &get_msg_plaintext(STARGAZE_WALLET_02.to_string()); + let eth_sig_str_2 = task::block_on(get_signature(wallet_1, claim_plaintext_2)) + .unwrap() + .to_string(); + + // claim with eth address 1, stargaze wallet 2 + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str_1.clone(), + eth_sig: eth_sig_str_2, + }; + let expected_error = + format!("Address {eth_addr_str_1} has already claimed all available mints"); + let res_2 = execute_contract_error_with_msg( + claim_message, + &mut app, + stargaze_wallet_02, + airdrop_contract, + ); + assert_eq!(res_2, expected_error); +} + +#[test] +fn test_two_claims_allowed_success() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT * 2 + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 2, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str.clone(), + eth_sig: eth_sig_str.clone(), + }; + let _ = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract.clone(), + ) + .unwrap(); + + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: eth_addr_str, + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract, + ) + .unwrap(); + + let balances = app.wrap().query_all_balances(stargaze_wallet_01).unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(2 * WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance) +} diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs new file mode 100644 index 000000000..e90494170 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs @@ -0,0 +1,91 @@ +use crate::common_setup::setup_accounts_and_block::setup_block_time; +use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ + CONFIG_PLAINTEXT, STARGAZE_WALLET_01, +}; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::{ + AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, +}; +use crate::sg_eth_airdrop::setup::dydx_airdrop::collection_whitelist_helpers::{ + execute_airdrop_claim, execute_mint_fail_not_on_whitelist, execute_mint_success, + send_funds_to_address, update_admin_for_whitelist, +}; +use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::instantiate_contract; +use crate::sg_eth_airdrop::setup::dydx_airdrop::setup_signatures::{ + get_msg_plaintext, get_wallet_and_sig, +}; +use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; +use cosmwasm_std::Addr; +use sg_eth_airdrop::dydx_airdrop::msg::QueryMsg; +use sg_std::GENESIS_MINT_START_TIME; +extern crate whitelist_immutable; +use crate::common_setup::templates::vending_minter_template; +use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; + +#[test] +fn test_set_minter_contract_success() { + let vt = vending_minter_template(1); + let (mut app, creator) = (vt.router, vt.accts.creator); + let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); + + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let contract_admin = Addr::unchecked(creator); + let params = InstantiateParams { + addresses: vec![eth_addr_str], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: contract_admin, + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + let airdrop_contract = Addr::unchecked("contract3"); + let query_msg = QueryMsg::GetMinter {}; + let result: Addr = app + .wrap() + .query_wasm_smart(airdrop_contract, &query_msg) + .unwrap(); + assert_eq!(result, minter_addr); +} + +#[test] +fn test_claim_added_to_minter_whitelist() { + let vt = vending_minter_template(1); + let (mut app, creator, buyer) = (vt.router, vt.accts.creator, vt.accts.buyer); + let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); + let whitelist_addr = + configure_collection_whitelist(&mut app, creator.clone(), buyer, minter_addr.clone()); + setup_block_time(&mut app, GENESIS_MINT_START_TIME, None); + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let airdrop_contract = Addr::unchecked(AIRDROP_ADDR_STR); + let params = InstantiateParams { + addresses: vec![eth_addr_str.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 5, + minter_address: minter_addr.clone(), + admin_account: creator.clone(), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + update_admin_for_whitelist(&mut app, creator, airdrop_contract.clone(), whitelist_addr); + send_funds_to_address(&mut app, STARGAZE_WALLET_01, MINT_PRICE); + execute_mint_fail_not_on_whitelist(&mut app, minter_addr.clone()); + execute_airdrop_claim( + &mut app, + eth_addr_str, + eth_sig_str, + stargaze_wallet_01.clone(), + airdrop_contract, + ); + execute_mint_success(&mut app, stargaze_wallet_01, minter_addr); +} diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs new file mode 100644 index 000000000..6a23357d5 --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs @@ -0,0 +1,187 @@ +use crate::common_setup::contract_boxes::custom_mock_app; +use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, OWNER, +}; +use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::sg_eth_airdrop::setup::dydx_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::instantiate_contract; +use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; + +use cosmwasm_std::Addr; +use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; +use sg_eth_airdrop::dydx_airdrop::msg::QueryMsg; +use whitelist_immutable::helpers::WhitelistImmutableContract; + +#[test] +fn test_instantiate_with_addresses() { + let addresses: Vec = vec![ + "addr1".to_string(), + "addr2".to_string(), + "addr3".to_string(), + ]; + + let mut app = { custom_mock_app }(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let params = InstantiateParams { + addresses, + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + + let query_msg = QueryMsg::AirdropEligible { + eth_address: "addr1".to_string(), + }; + let result: bool = app + .wrap() + .query_wasm_smart(airdrop_contract.clone(), &query_msg) + .unwrap(); + assert!(result); + + let query_msg = QueryMsg::AirdropEligible { + eth_address: "lies".to_string(), + }; + let result: bool = app + .wrap() + .query_wasm_smart(airdrop_contract, &query_msg) + .unwrap(); + assert!(!result); +} + +#[test] +fn test_whitelist_immutable_address_limit() { + let addresses: Vec = vec![ + "addr1".to_string(), + "addr2".to_string(), + "addr3".to_string(), + ]; + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + + let params = InstantiateParams { + addresses, + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 20, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + let whitelist_immutable = Addr::unchecked("contract4"); + let res: u32 = WhitelistImmutableContract(whitelist_immutable) + .per_address_limit(&app.wrap()) + .unwrap(); + assert_eq!(res, 20); +} + +#[test] +fn test_whitelist_immutable_address_count() { + let addresses: Vec = vec![ + "addr1".to_string(), + "addr2".to_string(), + "addr3".to_string(), + ]; + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + + let params = InstantiateParams { + addresses, + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 20, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + let whitelist_immutable = Addr::unchecked("contract4"); + let res: u64 = WhitelistImmutableContract(whitelist_immutable) + .address_count(&app.wrap()) + .unwrap(); + assert_eq!(res, 3); +} + +#[test] +fn test_whitelist_immutable_address_includes() { + let addresses: Vec = vec![ + "addr1".to_string(), + "addr2".to_string(), + "addr3".to_string(), + ]; + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + + let params = InstantiateParams { + addresses, + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 20, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + let whitelist_immutable = Addr::unchecked("contract4"); + let res: bool = WhitelistImmutableContract(whitelist_immutable.clone()) + .includes(&app.wrap(), "addr3".to_string()) + .unwrap(); + assert!(res); + + let res: bool = WhitelistImmutableContract(whitelist_immutable) + .includes(&app.wrap(), "nonsense".to_string()) + .unwrap(); + assert!(!res); +} + +#[test] +fn test_whitelist_immutable_address_config() { + let addresses: Vec = vec![ + "addr1".to_string(), + "addr2".to_string(), + "addr3".to_string(), + ]; + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + + let params = InstantiateParams { + addresses, + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr, + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 20, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + let whitelist_immutable = Addr::unchecked("contract4"); + let res: whitelist_immutable::state::Config = WhitelistImmutableContract(whitelist_immutable) + .config(&app.wrap()) + .unwrap(); + let expected_config = whitelist_immutable::state::Config { + admin: Addr::unchecked("contract3"), + per_address_limit: 20, + mint_discount_bps: Some(0), + }; + assert_eq!(res, expected_config); +} diff --git a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs new file mode 100644 index 000000000..da3fde61c --- /dev/null +++ b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs @@ -0,0 +1,3 @@ +mod test_claim; +mod test_collection_whitelist; +mod test_immutable_whitelist; diff --git a/test-suite/src/sg_eth_airdrop/tests/test_claim.rs b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs similarity index 97% rename from test-suite/src/sg_eth_airdrop/tests/test_claim.rs rename to test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs index 26572013a..85da99c7d 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_claim.rs +++ b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs @@ -1,10 +1,10 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::setup_signatures::{ +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::sg_eth_airdrop::setup::rekt_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::sg_eth_airdrop::setup::rekt_airdrop::setup_signatures::{ get_msg_plaintext, get_signature, get_wallet_and_sig, }; -use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; +use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; use async_std::task; use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, QueryMsg}; @@ -13,12 +13,12 @@ use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::sg_eth_airdrop::constants::claim_constants::{ +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, }; -use crate::sg_eth_airdrop::setup::execute_msg::{ +use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, }; diff --git a/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs similarity index 86% rename from test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs rename to test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs index 3bf3c7621..b13aba8e8 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs @@ -1,16 +1,20 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::sg_eth_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, STARGAZE_WALLET_01}; -use crate::sg_eth_airdrop::constants::collection_constants::{ +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ + CONFIG_PLAINTEXT, STARGAZE_WALLET_01, +}; +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; -use crate::sg_eth_airdrop::setup::collection_whitelist_helpers::{ +use crate::sg_eth_airdrop::setup::rekt_airdrop::collection_whitelist_helpers::{ execute_airdrop_claim, execute_mint_fail_not_on_whitelist, execute_mint_success, send_funds_to_address, update_admin_for_whitelist, }; -use crate::sg_eth_airdrop::setup::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::setup_signatures::{get_msg_plaintext, get_wallet_and_sig}; -use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; +use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::instantiate_contract; +use crate::sg_eth_airdrop::setup::rekt_airdrop::setup_signatures::{ + get_msg_plaintext, get_wallet_and_sig, +}; +use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; use cosmwasm_std::Addr; use sg_eth_airdrop::rekt_airdrop::msg::QueryMsg; use sg_std::GENESIS_MINT_START_TIME; diff --git a/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs similarity index 93% rename from test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs rename to test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs index a9855aee8..f2e2a4e89 100644 --- a/test-suite/src/sg_eth_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs @@ -1,11 +1,11 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::claim_constants::{ +use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, OWNER, }; -use crate::sg_eth_airdrop::constants::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::test_msgs::InstantiateParams; +use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::sg_eth_airdrop::setup::rekt_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::instantiate_contract; +use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; use cosmwasm_std::Addr; use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; From d5ba86e025fdb45f029b3d30aab8a1d71f694897 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 14:53:58 -0800 Subject: [PATCH 05/42] creating duplicate file structure in two top level folders --- .circleci/config.yml | 54 ++++++- Cargo.lock | 108 ++++++++----- Cargo.toml | 9 +- .../.cargo/config | 0 .../.gitignore | 0 .../Cargo.toml | 4 +- .../rustfmt.toml | 0 .../schema/dydx-airdrop.json} | 2 +- .../dydx-airdrop/schema/raw/execute.json | 31 ++++ .../dydx-airdrop/schema/raw/instantiate.json | 53 +++++++ contracts/dydx-airdrop/schema/raw/query.json | 40 +++++ .../raw/response_to_airdrop_eligible.json | 5 + .../schema/raw/response_to_get_minter.json | 6 + .../src/bin/schema.rs | 2 +- .../src}/claim_airdrop.rs | 10 +- .../src}/contract.rs | 12 +- .../src}/error.rs | 0 .../src/lib.rs} | 2 +- .../dydx_airdrop => dydx-airdrop/src}/msg.rs | 0 .../src}/query.rs | 2 +- .../src}/reply.rs | 4 +- .../src}/state.rs | 0 contracts/rekt-airdrop/.cargo/config | 5 + contracts/rekt-airdrop/.gitignore | 15 ++ contracts/rekt-airdrop/Cargo.toml | 59 +++++++ contracts/rekt-airdrop/rustfmt.toml | 14 ++ .../rekt-airdrop/schema/raw/execute.json | 31 ++++ .../rekt-airdrop/schema/raw/instantiate.json | 53 +++++++ contracts/rekt-airdrop/schema/raw/query.json | 40 +++++ .../raw/response_to_airdrop_eligible.json | 5 + .../schema/raw/response_to_get_minter.json | 6 + .../rekt-airdrop/schema/rekt-airdrop.json | 144 ++++++++++++++++++ contracts/rekt-airdrop/src/bin/schema.rs | 11 ++ .../src}/claim_airdrop.rs | 10 +- .../src}/contract.rs | 12 +- .../src}/error.rs | 0 .../src/lib.rs} | 2 +- .../rekt_airdrop => rekt-airdrop/src}/msg.rs | 0 .../src}/query.rs | 2 +- .../src}/reply.rs | 4 +- .../src}/state.rs | 0 contracts/sg-eth-airdrop/src/lib.rs | 2 - scripts/publish-contracts.sh | 4 +- scripts/schema.sh | 3 +- test-suite/Cargo.toml | 3 +- test-suite/src/common_setup/contract_boxes.rs | 8 +- .../{sg_eth_airdrop.rs => dydx_airdrop.rs} | 0 .../constants.rs} | 0 .../constants}/claim_constants.rs | 0 .../constants}/collection_constants.rs | 0 .../dydx_airdrop.rs => dydx_airdrop/setup.rs} | 0 .../setup}/collection_whitelist_helpers.rs | 12 +- .../setup}/configure_mock_minter.rs | 6 +- .../setup}/execute_msg.rs | 8 +- .../setup}/mock_minter_contract.rs | 6 +- .../setup}/mock_whitelist_contract.rs | 2 +- .../setup}/setup_signatures.rs | 2 +- .../setup}/test_msgs.rs | 0 .../dydx_airdrop.rs => dydx_airdrop/tests.rs} | 0 .../tests}/test_claim.rs | 16 +- .../tests}/test_collection_whitelist.rs | 20 +-- .../tests}/test_immutable_whitelist.rs | 14 +- test-suite/src/lib.rs | 9 +- test-suite/src/rekt_airdrop.rs | 3 + .../constants.rs} | 0 .../constants}/claim_constants.rs | 0 .../constants}/collection_constants.rs | 0 .../rekt_airdrop.rs => rekt_airdrop/setup.rs} | 0 .../setup}/collection_whitelist_helpers.rs | 12 +- .../setup}/configure_mock_minter.rs | 6 +- .../setup}/execute_msg.rs | 8 +- .../setup}/mock_minter_contract.rs | 6 +- .../setup}/mock_whitelist_contract.rs | 2 +- .../setup}/setup_signatures.rs | 2 +- .../setup}/test_msgs.rs | 0 .../rekt_airdrop.rs => rekt_airdrop/tests.rs} | 0 .../tests}/test_claim.rs | 16 +- .../tests}/test_collection_whitelist.rs | 20 +-- .../tests}/test_immutable_whitelist.rs | 14 +- test-suite/src/sg_eth_airdrop/constants.rs | 2 - test-suite/src/sg_eth_airdrop/setup.rs | 2 - test-suite/src/sg_eth_airdrop/tests.rs | 2 - 82 files changed, 776 insertions(+), 191 deletions(-) rename contracts/{sg-eth-airdrop => dydx-airdrop}/.cargo/config (100%) rename contracts/{sg-eth-airdrop => dydx-airdrop}/.gitignore (100%) rename contracts/{sg-eth-airdrop => dydx-airdrop}/Cargo.toml (96%) rename contracts/{sg-eth-airdrop => dydx-airdrop}/rustfmt.toml (100%) rename contracts/{sg-eth-airdrop/schema/sg-eth-airdrop.json => dydx-airdrop/schema/dydx-airdrop.json} (99%) create mode 100644 contracts/dydx-airdrop/schema/raw/execute.json create mode 100644 contracts/dydx-airdrop/schema/raw/instantiate.json create mode 100644 contracts/dydx-airdrop/schema/raw/query.json create mode 100644 contracts/dydx-airdrop/schema/raw/response_to_airdrop_eligible.json create mode 100644 contracts/dydx-airdrop/schema/raw/response_to_get_minter.json rename contracts/{sg-eth-airdrop => dydx-airdrop}/src/bin/schema.rs (67%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => dydx-airdrop/src}/claim_airdrop.rs (94%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => dydx-airdrop/src}/contract.rs (93%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => dydx-airdrop/src}/error.rs (100%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop.rs => dydx-airdrop/src/lib.rs} (68%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => dydx-airdrop/src}/msg.rs (100%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => dydx-airdrop/src}/query.rs (96%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => dydx-airdrop/src}/reply.rs (93%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => dydx-airdrop/src}/state.rs (100%) create mode 100644 contracts/rekt-airdrop/.cargo/config create mode 100644 contracts/rekt-airdrop/.gitignore create mode 100644 contracts/rekt-airdrop/Cargo.toml create mode 100644 contracts/rekt-airdrop/rustfmt.toml create mode 100644 contracts/rekt-airdrop/schema/raw/execute.json create mode 100644 contracts/rekt-airdrop/schema/raw/instantiate.json create mode 100644 contracts/rekt-airdrop/schema/raw/query.json create mode 100644 contracts/rekt-airdrop/schema/raw/response_to_airdrop_eligible.json create mode 100644 contracts/rekt-airdrop/schema/raw/response_to_get_minter.json create mode 100644 contracts/rekt-airdrop/schema/rekt-airdrop.json create mode 100644 contracts/rekt-airdrop/src/bin/schema.rs rename contracts/{sg-eth-airdrop/src/rekt_airdrop => rekt-airdrop/src}/claim_airdrop.rs (94%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => rekt-airdrop/src}/contract.rs (93%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => rekt-airdrop/src}/error.rs (100%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop.rs => rekt-airdrop/src/lib.rs} (68%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => rekt-airdrop/src}/msg.rs (100%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => rekt-airdrop/src}/query.rs (96%) rename contracts/{sg-eth-airdrop/src/dydx_airdrop => rekt-airdrop/src}/reply.rs (93%) rename contracts/{sg-eth-airdrop/src/rekt_airdrop => rekt-airdrop/src}/state.rs (100%) delete mode 100644 contracts/sg-eth-airdrop/src/lib.rs rename test-suite/src/{sg_eth_airdrop.rs => dydx_airdrop.rs} (100%) rename test-suite/src/{sg_eth_airdrop/constants/dydx_airdrop.rs => dydx_airdrop/constants.rs} (100%) rename test-suite/src/{sg_eth_airdrop/constants/dydx_airdrop => dydx_airdrop/constants}/claim_constants.rs (100%) rename test-suite/src/{sg_eth_airdrop/constants/dydx_airdrop => dydx_airdrop/constants}/collection_constants.rs (100%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop.rs => dydx_airdrop/setup.rs} (100%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => dydx_airdrop/setup}/collection_whitelist_helpers.rs (84%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => dydx_airdrop/setup}/configure_mock_minter.rs (88%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => dydx_airdrop/setup}/execute_msg.rs (88%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => dydx_airdrop/setup}/mock_minter_contract.rs (92%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => dydx_airdrop/setup}/mock_whitelist_contract.rs (95%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => dydx_airdrop/setup}/setup_signatures.rs (91%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => dydx_airdrop/setup}/test_msgs.rs (100%) rename test-suite/src/{sg_eth_airdrop/tests/dydx_airdrop.rs => dydx_airdrop/tests.rs} (100%) rename test-suite/src/{sg_eth_airdrop/tests/dydx_airdrop => dydx_airdrop/tests}/test_claim.rs (97%) rename test-suite/src/{sg_eth_airdrop/tests/rekt_airdrop => dydx_airdrop/tests}/test_collection_whitelist.rs (83%) rename test-suite/src/{sg_eth_airdrop/tests/dydx_airdrop => dydx_airdrop/tests}/test_immutable_whitelist.rs (91%) create mode 100644 test-suite/src/rekt_airdrop.rs rename test-suite/src/{sg_eth_airdrop/constants/rekt_airdrop.rs => rekt_airdrop/constants.rs} (100%) rename test-suite/src/{sg_eth_airdrop/constants/rekt_airdrop => rekt_airdrop/constants}/claim_constants.rs (100%) rename test-suite/src/{sg_eth_airdrop/constants/rekt_airdrop => rekt_airdrop/constants}/collection_constants.rs (100%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop.rs => rekt_airdrop/setup.rs} (100%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => rekt_airdrop/setup}/collection_whitelist_helpers.rs (84%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => rekt_airdrop/setup}/configure_mock_minter.rs (88%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => rekt_airdrop/setup}/execute_msg.rs (88%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => rekt_airdrop/setup}/mock_minter_contract.rs (92%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => rekt_airdrop/setup}/mock_whitelist_contract.rs (95%) rename test-suite/src/{sg_eth_airdrop/setup/dydx_airdrop => rekt_airdrop/setup}/setup_signatures.rs (91%) rename test-suite/src/{sg_eth_airdrop/setup/rekt_airdrop => rekt_airdrop/setup}/test_msgs.rs (100%) rename test-suite/src/{sg_eth_airdrop/tests/rekt_airdrop.rs => rekt_airdrop/tests.rs} (100%) rename test-suite/src/{sg_eth_airdrop/tests/rekt_airdrop => rekt_airdrop/tests}/test_claim.rs (97%) rename test-suite/src/{sg_eth_airdrop/tests/dydx_airdrop => rekt_airdrop/tests}/test_collection_whitelist.rs (83%) rename test-suite/src/{sg_eth_airdrop/tests/rekt_airdrop => rekt_airdrop/tests}/test_immutable_whitelist.rs (91%) delete mode 100644 test-suite/src/sg_eth_airdrop/constants.rs delete mode 100644 test-suite/src/sg_eth_airdrop/setup.rs delete mode 100644 test-suite/src/sg_eth_airdrop/tests.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 3e1d23ed2..2e7264036 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,8 @@ workflows: - contract_open_edition_factory - contract_open_edition_minter - contract_whitelist - - sg-eth-airdrop + - rekt-airdrop + - dydx-airdrop - test-suite - package_sg_std - package_sg_utils @@ -424,10 +425,10 @@ jobs: - target key: cargocache-sg-utils-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} - sg-eth-airdrop: + rekt-airdrop: docker: - image: rust:1.73.0 - working_directory: ~/project/contracts/sg-eth-airdrop + working_directory: ~/project/contracts/rekt-airdrop steps: - checkout: path: ~/project @@ -436,7 +437,7 @@ jobs: command: rustc --version; cargo --version; rustup --version - restore_cache: keys: - - cargocache-sg-eth-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} + - cargocache-rekt-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} - run: name: Unit Tests environment: @@ -458,7 +459,43 @@ jobs: paths: - /usr/local/cargo/registry - target - key: cargocache-sg-eth-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} + key: cargocache-rekt-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} + + dydx-airdrop: + docker: + - image: rust:1.73.0 + working_directory: ~/project/contracts/dydx-airdrop + steps: + - checkout: + path: ~/project + - run: + name: Version information + command: rustc --version; cargo --version; rustup --version + - restore_cache: + keys: + - cargocache-dydx-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} + - run: + name: Unit Tests + environment: + RUST_BACKTRACE: 1 + command: cargo unit-test --locked + - run: + name: Build and run schema generator + command: cargo schema --locked + # - run: + # name: Ensure checked-in schemas are up-to-date + # command: | + # CHANGES_IN_REPO=$(git status --porcelain) + # if [[ -n "$CHANGES_IN_REPO" ]]; then + # echo "Repository is dirty. Showing 'git status' and 'git --no-pager diff' for debugging now:" + # git status && git --no-pager diff + # exit 1 + # fi + - save_cache: + paths: + - /usr/local/cargo/registry + - target + key: cargocache-dydx-airdrop-rust:1.73.0-{{ checksum "~/project/Cargo.lock" }} lint: docker: @@ -528,7 +565,12 @@ jobs: echo "Compiling `basename $C`..." (cd $C && cargo build --release --lib --target wasm32-unknown-unknown --locked) done - for C in ./contracts/sg-eth-airdrop/ + for C in ./contracts/rekt-airdrop/ + do + echo "Compiling `basename $C`..." + (cd $C && cargo build --release --lib --target wasm32-unknown-unknown --locked) + done + for C in ./contracts/dxdy-airdrop/ do echo "Compiling `basename $C`..." (cd $C && cargo build --release --lib --target wasm32-unknown-unknown --locked) diff --git a/Cargo.lock b/Cargo.lock index 5fb111ff8..d11306011 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1347,6 +1347,41 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +[[package]] +name = "dydx-airdrop" +version = "3.5.0" +dependencies = [ + "anyhow", + "async-std", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.1.0", + "ethereum-verify", + "ethers-core", + "ethers-signers", + "eyre", + "hex", + "rlp", + "rust_decimal", + "schemars", + "serde", + "sg-multi-test", + "sg-std", + "sg-whitelist", + "sg1", + "sg2", + "sg721-base", + "sha2 0.10.7", + "sha3", + "thiserror", + "vending-factory", + "vending-minter", + "whitelist-immutable", +] + [[package]] name = "dyn-clone" version = "1.0.13" @@ -3018,6 +3053,41 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "rekt-airdrop" +version = "3.5.0" +dependencies = [ + "anyhow", + "async-std", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.1.0", + "ethereum-verify", + "ethers-core", + "ethers-signers", + "eyre", + "hex", + "rlp", + "rust_decimal", + "schemars", + "serde", + "sg-multi-test", + "sg-std", + "sg-whitelist", + "sg1", + "sg2", + "sg721-base", + "sha2 0.10.7", + "sha3", + "thiserror", + "vending-factory", + "vending-minter", + "whitelist-immutable", +] + [[package]] name = "rend" version = "0.4.0" @@ -3486,41 +3556,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "sg-eth-airdrop" -version = "3.5.0" -dependencies = [ - "anyhow", - "async-std", - "cosmwasm-schema", - "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.1", - "cw2 1.1.0", - "ethereum-verify", - "ethers-core", - "ethers-signers", - "eyre", - "hex", - "rlp", - "rust_decimal", - "schemars", - "serde", - "sg-multi-test", - "sg-std", - "sg-whitelist", - "sg1", - "sg2", - "sg721-base", - "sha2 0.10.7", - "sha3", - "thiserror", - "vending-factory", - "vending-minter", - "whitelist-immutable", -] - [[package]] name = "sg-metadata" version = "3.5.0" @@ -4132,6 +4167,7 @@ dependencies = [ "cw4-group", "cw721 0.18.0", "cw721-base 0.18.0", + "dydx-airdrop", "ethers-core", "ethers-signers", "eyre", @@ -4139,12 +4175,12 @@ dependencies = [ "open-edition-minter", "rand_core 0.6.4", "rand_xoshiro", + "rekt-airdrop", "rlp", "rs_merkle", "schemars", "serde", "sg-controllers", - "sg-eth-airdrop", "sg-metadata", "sg-multi-test", "sg-splits", diff --git a/Cargo.toml b/Cargo.toml index b86fb6c15..57fd87591 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,8 @@ open-edition-minter = { version = "3.5.0", path = "contracts/minters/open-editi whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable" } sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } -sg-eth-airdrop = { version = "3.5.0", path = "contracts/sg-eth-airdrop" } +rekt-airdrop = { version = "3.5.0", path = "contracts/rekt-airdrop"} +dydx-airdrop = { version = "3.5.0", path = "contracts/dydx-airdrop"} test-suite = { version = "3.5.0", path = "test-suite" } semver = "1" @@ -107,7 +108,11 @@ incremental = false codegen-units = 1 incremental = false -[profile.release.package.sg-eth-airdrop] +[profile.release.package.rekt-airdrop] +codegen-units = 1 +incremental = false + +[profile.release.package.dydx-airdrop] codegen-units = 1 incremental = false diff --git a/contracts/sg-eth-airdrop/.cargo/config b/contracts/dydx-airdrop/.cargo/config similarity index 100% rename from contracts/sg-eth-airdrop/.cargo/config rename to contracts/dydx-airdrop/.cargo/config diff --git a/contracts/sg-eth-airdrop/.gitignore b/contracts/dydx-airdrop/.gitignore similarity index 100% rename from contracts/sg-eth-airdrop/.gitignore rename to contracts/dydx-airdrop/.gitignore diff --git a/contracts/sg-eth-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml similarity index 96% rename from contracts/sg-eth-airdrop/Cargo.toml rename to contracts/dydx-airdrop/Cargo.toml index ffb4ec5fd..903f925ac 100644 --- a/contracts/sg-eth-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "sg-eth-airdrop" +name = "dydx-airdrop" authors = ["Michael Scotto "] -description = "Stargaze Ethereum Airdrop" +description = "Stargaze dydx Airdrop" version = { workspace = true } edition = { workspace = true } homepage = { workspace = true } diff --git a/contracts/sg-eth-airdrop/rustfmt.toml b/contracts/dydx-airdrop/rustfmt.toml similarity index 100% rename from contracts/sg-eth-airdrop/rustfmt.toml rename to contracts/dydx-airdrop/rustfmt.toml diff --git a/contracts/sg-eth-airdrop/schema/sg-eth-airdrop.json b/contracts/dydx-airdrop/schema/dydx-airdrop.json similarity index 99% rename from contracts/sg-eth-airdrop/schema/sg-eth-airdrop.json rename to contracts/dydx-airdrop/schema/dydx-airdrop.json index ddee384ab..9217af847 100644 --- a/contracts/sg-eth-airdrop/schema/sg-eth-airdrop.json +++ b/contracts/dydx-airdrop/schema/dydx-airdrop.json @@ -1,5 +1,5 @@ { - "contract_name": "sg-eth-airdrop", + "contract_name": "dydx-airdrop", "contract_version": "3.5.0", "idl_version": "1.0.0", "instantiate": { diff --git a/contracts/dydx-airdrop/schema/raw/execute.json b/contracts/dydx-airdrop/schema/raw/execute.json new file mode 100644 index 000000000..78ab6b551 --- /dev/null +++ b/contracts/dydx-airdrop/schema/raw/execute.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "claim_airdrop" + ], + "properties": { + "claim_airdrop": { + "type": "object", + "required": [ + "eth_address", + "eth_sig" + ], + "properties": { + "eth_address": { + "type": "string" + }, + "eth_sig": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/dydx-airdrop/schema/raw/instantiate.json b/contracts/dydx-airdrop/schema/raw/instantiate.json new file mode 100644 index 000000000..d7e7e85ad --- /dev/null +++ b/contracts/dydx-airdrop/schema/raw/instantiate.json @@ -0,0 +1,53 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "addresses", + "admin", + "airdrop_amount", + "claim_msg_plaintext", + "minter_address", + "per_address_limit", + "whitelist_code_id" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + } + }, + "admin": { + "$ref": "#/definitions/Addr" + }, + "airdrop_amount": { + "type": "integer", + "format": "uint128", + "minimum": 0.0 + }, + "claim_msg_plaintext": { + "type": "string" + }, + "minter_address": { + "$ref": "#/definitions/Addr" + }, + "per_address_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "whitelist_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/dydx-airdrop/schema/raw/query.json b/contracts/dydx-airdrop/schema/raw/query.json new file mode 100644 index 000000000..c21aaf535 --- /dev/null +++ b/contracts/dydx-airdrop/schema/raw/query.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "airdrop_eligible" + ], + "properties": { + "airdrop_eligible": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_minter" + ], + "properties": { + "get_minter": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/dydx-airdrop/schema/raw/response_to_airdrop_eligible.json b/contracts/dydx-airdrop/schema/raw/response_to_airdrop_eligible.json new file mode 100644 index 000000000..a7fe2bfe9 --- /dev/null +++ b/contracts/dydx-airdrop/schema/raw/response_to_airdrop_eligible.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" +} diff --git a/contracts/dydx-airdrop/schema/raw/response_to_get_minter.json b/contracts/dydx-airdrop/schema/raw/response_to_get_minter.json new file mode 100644 index 000000000..4c7f1934d --- /dev/null +++ b/contracts/dydx-airdrop/schema/raw/response_to_get_minter.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Addr", + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" +} diff --git a/contracts/sg-eth-airdrop/src/bin/schema.rs b/contracts/dydx-airdrop/src/bin/schema.rs similarity index 67% rename from contracts/sg-eth-airdrop/src/bin/schema.rs rename to contracts/dydx-airdrop/src/bin/schema.rs index 3560190b9..2a15dd0fd 100644 --- a/contracts/sg-eth-airdrop/src/bin/schema.rs +++ b/contracts/dydx-airdrop/src/bin/schema.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::write_api; -use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; fn main() { write_api! { diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs similarity index 94% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs rename to contracts/dydx-airdrop/src/claim_airdrop.rs index f7f1c9700..7ac8d199a 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -1,6 +1,6 @@ -use crate::dydx_airdrop::query::query_collection_whitelist; -use crate::dydx_airdrop::state::ADDRS_TO_MINT_COUNT; -use crate::dydx_airdrop::{state::CONFIG, ContractError}; +use crate::query::query_collection_whitelist; +use crate::state::ADDRS_TO_MINT_COUNT; +use crate::{state::CONFIG, ContractError}; use build_messages::claim_and_whitelist_add; use cosmwasm_std::DepsMut; use cosmwasm_std::{coins, Addr, BankMsg, StdResult}; @@ -88,8 +88,8 @@ mod validation { use ethereum_verify::verify_ethereum_text; use crate::{ - dydx_airdrop::query::{query_airdrop_is_eligible, query_per_address_limit}, - dydx_airdrop::state::Config, + query::{query_airdrop_is_eligible, query_per_address_limit}, + state::Config, }; pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs b/contracts/dydx-airdrop/src/contract.rs similarity index 93% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs rename to contracts/dydx-airdrop/src/contract.rs index 9807ffb4a..d6253bd32 100644 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -1,8 +1,8 @@ -use crate::rekt_airdrop::claim_airdrop::claim_airdrop; +use crate::claim_airdrop::claim_airdrop; #[cfg(not(feature = "library"))] -use crate::rekt_airdrop::error::ContractError; -use crate::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg}; -use crate::rekt_airdrop::state::CONFIG; +use crate::error::ContractError; +use crate::msg::{ExecuteMsg, InstantiateMsg}; +use crate::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, MessageInfo}; @@ -13,7 +13,7 @@ use sg_std::Response; use build_message::{state_config, whitelist_instantiate}; use validation::validate_instantiation_params; -const CONTRACT_NAME: &str = "crates.io:sg-eth-airdrop"; +const CONTRACT_NAME: &str = "crates.io:dydx-airdrop"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const INSTANTIATION_FEE: u128 = 100_000_000; // 100 STARS @@ -55,7 +55,7 @@ pub fn execute( mod build_message { use super::*; - use crate::rekt_airdrop::state::Config; + use crate::state::Config; use cosmwasm_std::{to_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs b/contracts/dydx-airdrop/src/error.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/error.rs rename to contracts/dydx-airdrop/src/error.rs diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop.rs b/contracts/dydx-airdrop/src/lib.rs similarity index 68% rename from contracts/sg-eth-airdrop/src/rekt_airdrop.rs rename to contracts/dydx-airdrop/src/lib.rs index 48e0a4163..76387429a 100644 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop.rs +++ b/contracts/dydx-airdrop/src/lib.rs @@ -4,5 +4,5 @@ pub mod msg; pub mod query; pub mod reply; pub mod state; -pub use crate::rekt_airdrop::error::ContractError; +pub use crate::error::ContractError; mod claim_airdrop; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs b/contracts/dydx-airdrop/src/msg.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/msg.rs rename to contracts/dydx-airdrop/src/msg.rs diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs b/contracts/dydx-airdrop/src/query.rs similarity index 96% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs rename to contracts/dydx-airdrop/src/query.rs index d7b06a8df..c3b50fcd1 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -1,4 +1,4 @@ -use crate::dydx_airdrop::{msg::QueryMsg, state::CONFIG, ContractError}; +use crate::{msg::QueryMsg, state::CONFIG, ContractError}; use cosmwasm_std::{entry_point, to_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs b/contracts/dydx-airdrop/src/reply.rs similarity index 93% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs rename to contracts/dydx-airdrop/src/reply.rs index cd4d40ada..90f98d77b 100644 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop/reply.rs +++ b/contracts/dydx-airdrop/src/reply.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] -use crate::rekt_airdrop::error::ContractError; -use crate::rekt_airdrop::state::CONFIG; +use crate::error::ContractError; +use crate::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, Reply}; use cw_utils::{parse_reply_instantiate_data, MsgInstantiateContractResponse, ParseReplyError}; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs b/contracts/dydx-airdrop/src/state.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/state.rs rename to contracts/dydx-airdrop/src/state.rs diff --git a/contracts/rekt-airdrop/.cargo/config b/contracts/rekt-airdrop/.cargo/config new file mode 100644 index 000000000..de2d36ac7 --- /dev/null +++ b/contracts/rekt-airdrop/.cargo/config @@ -0,0 +1,5 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +wasm-debug = "build --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --bin schema" diff --git a/contracts/rekt-airdrop/.gitignore b/contracts/rekt-airdrop/.gitignore new file mode 100644 index 000000000..dfdaaa6bc --- /dev/null +++ b/contracts/rekt-airdrop/.gitignore @@ -0,0 +1,15 @@ +# Build results +/target + +# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327) +.cargo-ok + +# Text file backups +**/*.rs.bk + +# macOS +.DS_Store + +# IDEs +*.iml +.idea diff --git a/contracts/rekt-airdrop/Cargo.toml b/contracts/rekt-airdrop/Cargo.toml new file mode 100644 index 000000000..c01cc3cc7 --- /dev/null +++ b/contracts/rekt-airdrop/Cargo.toml @@ -0,0 +1,59 @@ +[package] +name = "rekt-airdrop" +authors = ["Michael Scotto "] +description = "Stargaze Rekt Airdrop" +version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +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. + "contract.wasm", + "hash.txt", +] + +# 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] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw-utils = { workspace = true } +cw2 = { workspace = true } +ethereum-verify = { workspace = true } +hex = "0.4" +rust_decimal = { version = "1.14.3" } +sg-whitelist = { workspace = true } +sg1 = { workspace = true } +sha2 = { workspace = true } +sha3 = "0.10" +schemars = { workspace = true } +serde = { workspace = true } +sg-std = { workspace = true } +thiserror = { workspace = true } +vending-minter = { workspace = true, features = ["library"] } +whitelist-immutable = { workspace = true, features = ["library"] } + +[dev-dependencies] +async-std = "1.12.0" +ethers-signers = "1.0.0" +ethers-core = "1.0.0" +eyre = "0.6" +rlp = "0.5" +sg2 = { workspace = true } +vending-factory = { workspace = true } +sg721-base = { workspace = true } +cw-multi-test = { workspace = true } +sg-multi-test = { workspace = true } +anyhow = "1.0.57" diff --git a/contracts/rekt-airdrop/rustfmt.toml b/contracts/rekt-airdrop/rustfmt.toml new file mode 100644 index 000000000..6918e2237 --- /dev/null +++ b/contracts/rekt-airdrop/rustfmt.toml @@ -0,0 +1,14 @@ +# stable +newline_style = "unix" +hard_tabs = false +tab_spaces = 4 + +# unstable... should we require `rustup run nightly cargo fmt` ? +# or just update the style guide when they are stable? +#fn_single_line = true +#format_code_in_doc_comments = true +#overflow_delimited_expr = true +#reorder_impl_items = true +#struct_field_align_threshold = 20 +#struct_lit_single_line = true +#report_todo = "Always" diff --git a/contracts/rekt-airdrop/schema/raw/execute.json b/contracts/rekt-airdrop/schema/raw/execute.json new file mode 100644 index 000000000..78ab6b551 --- /dev/null +++ b/contracts/rekt-airdrop/schema/raw/execute.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "claim_airdrop" + ], + "properties": { + "claim_airdrop": { + "type": "object", + "required": [ + "eth_address", + "eth_sig" + ], + "properties": { + "eth_address": { + "type": "string" + }, + "eth_sig": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/rekt-airdrop/schema/raw/instantiate.json b/contracts/rekt-airdrop/schema/raw/instantiate.json new file mode 100644 index 000000000..d7e7e85ad --- /dev/null +++ b/contracts/rekt-airdrop/schema/raw/instantiate.json @@ -0,0 +1,53 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "addresses", + "admin", + "airdrop_amount", + "claim_msg_plaintext", + "minter_address", + "per_address_limit", + "whitelist_code_id" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + } + }, + "admin": { + "$ref": "#/definitions/Addr" + }, + "airdrop_amount": { + "type": "integer", + "format": "uint128", + "minimum": 0.0 + }, + "claim_msg_plaintext": { + "type": "string" + }, + "minter_address": { + "$ref": "#/definitions/Addr" + }, + "per_address_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "whitelist_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/rekt-airdrop/schema/raw/query.json b/contracts/rekt-airdrop/schema/raw/query.json new file mode 100644 index 000000000..c21aaf535 --- /dev/null +++ b/contracts/rekt-airdrop/schema/raw/query.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "airdrop_eligible" + ], + "properties": { + "airdrop_eligible": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_minter" + ], + "properties": { + "get_minter": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/rekt-airdrop/schema/raw/response_to_airdrop_eligible.json b/contracts/rekt-airdrop/schema/raw/response_to_airdrop_eligible.json new file mode 100644 index 000000000..a7fe2bfe9 --- /dev/null +++ b/contracts/rekt-airdrop/schema/raw/response_to_airdrop_eligible.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" +} diff --git a/contracts/rekt-airdrop/schema/raw/response_to_get_minter.json b/contracts/rekt-airdrop/schema/raw/response_to_get_minter.json new file mode 100644 index 000000000..4c7f1934d --- /dev/null +++ b/contracts/rekt-airdrop/schema/raw/response_to_get_minter.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Addr", + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" +} diff --git a/contracts/rekt-airdrop/schema/rekt-airdrop.json b/contracts/rekt-airdrop/schema/rekt-airdrop.json new file mode 100644 index 000000000..2a3cbbf3c --- /dev/null +++ b/contracts/rekt-airdrop/schema/rekt-airdrop.json @@ -0,0 +1,144 @@ +{ + "contract_name": "rekt-airdrop", + "contract_version": "3.5.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "addresses", + "admin", + "airdrop_amount", + "claim_msg_plaintext", + "minter_address", + "per_address_limit", + "whitelist_code_id" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + } + }, + "admin": { + "$ref": "#/definitions/Addr" + }, + "airdrop_amount": { + "type": "integer", + "format": "uint128", + "minimum": 0.0 + }, + "claim_msg_plaintext": { + "type": "string" + }, + "minter_address": { + "$ref": "#/definitions/Addr" + }, + "per_address_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "whitelist_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "claim_airdrop" + ], + "properties": { + "claim_airdrop": { + "type": "object", + "required": [ + "eth_address", + "eth_sig" + ], + "properties": { + "eth_address": { + "type": "string" + }, + "eth_sig": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "airdrop_eligible" + ], + "properties": { + "airdrop_eligible": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_minter" + ], + "properties": { + "get_minter": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "airdrop_eligible": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" + }, + "get_minter": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Addr", + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/rekt-airdrop/src/bin/schema.rs b/contracts/rekt-airdrop/src/bin/schema.rs new file mode 100644 index 000000000..faf5130f3 --- /dev/null +++ b/contracts/rekt-airdrop/src/bin/schema.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::write_api; + +use rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs b/contracts/rekt-airdrop/src/claim_airdrop.rs similarity index 94% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs rename to contracts/rekt-airdrop/src/claim_airdrop.rs index 816766a40..7ac8d199a 100644 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop/claim_airdrop.rs +++ b/contracts/rekt-airdrop/src/claim_airdrop.rs @@ -1,6 +1,6 @@ -use crate::rekt_airdrop::query::query_collection_whitelist; -use crate::rekt_airdrop::state::ADDRS_TO_MINT_COUNT; -use crate::rekt_airdrop::{state::CONFIG, ContractError}; +use crate::query::query_collection_whitelist; +use crate::state::ADDRS_TO_MINT_COUNT; +use crate::{state::CONFIG, ContractError}; use build_messages::claim_and_whitelist_add; use cosmwasm_std::DepsMut; use cosmwasm_std::{coins, Addr, BankMsg, StdResult}; @@ -88,8 +88,8 @@ mod validation { use ethereum_verify::verify_ethereum_text; use crate::{ - rekt_airdrop::query::{query_airdrop_is_eligible, query_per_address_limit}, - rekt_airdrop::state::Config, + query::{query_airdrop_is_eligible, query_per_address_limit}, + state::Config, }; pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs b/contracts/rekt-airdrop/src/contract.rs similarity index 93% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs rename to contracts/rekt-airdrop/src/contract.rs index f1c434057..04c3b8982 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop/contract.rs +++ b/contracts/rekt-airdrop/src/contract.rs @@ -1,8 +1,8 @@ -use crate::dydx_airdrop::claim_airdrop::claim_airdrop; +use crate::claim_airdrop::claim_airdrop; #[cfg(not(feature = "library"))] -use crate::dydx_airdrop::error::ContractError; -use crate::dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg}; -use crate::dydx_airdrop::state::CONFIG; +use crate::error::ContractError; +use crate::msg::{ExecuteMsg, InstantiateMsg}; +use crate::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, MessageInfo}; @@ -13,7 +13,7 @@ use sg_std::Response; use build_message::{state_config, whitelist_instantiate}; use validation::validate_instantiation_params; -const CONTRACT_NAME: &str = "crates.io:sg-eth-airdrop"; +const CONTRACT_NAME: &str = "crates.io:rekt-airdrop"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const INSTANTIATION_FEE: u128 = 100_000_000; // 100 STARS @@ -55,7 +55,7 @@ pub fn execute( mod build_message { use super::*; - use crate::dydx_airdrop::state::Config; + use crate::state::Config; use cosmwasm_std::{to_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/error.rs b/contracts/rekt-airdrop/src/error.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/error.rs rename to contracts/rekt-airdrop/src/error.rs diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs b/contracts/rekt-airdrop/src/lib.rs similarity index 68% rename from contracts/sg-eth-airdrop/src/dydx_airdrop.rs rename to contracts/rekt-airdrop/src/lib.rs index 25e7b3286..76387429a 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop.rs +++ b/contracts/rekt-airdrop/src/lib.rs @@ -4,5 +4,5 @@ pub mod msg; pub mod query; pub mod reply; pub mod state; -pub use crate::dydx_airdrop::error::ContractError; +pub use crate::error::ContractError; mod claim_airdrop; diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/msg.rs b/contracts/rekt-airdrop/src/msg.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/msg.rs rename to contracts/rekt-airdrop/src/msg.rs diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs b/contracts/rekt-airdrop/src/query.rs similarity index 96% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs rename to contracts/rekt-airdrop/src/query.rs index d1c34cd5c..c3b50fcd1 100644 --- a/contracts/sg-eth-airdrop/src/rekt_airdrop/query.rs +++ b/contracts/rekt-airdrop/src/query.rs @@ -1,4 +1,4 @@ -use crate::rekt_airdrop::{msg::QueryMsg, state::CONFIG, ContractError}; +use crate::{msg::QueryMsg, state::CONFIG, ContractError}; use cosmwasm_std::{entry_point, to_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; diff --git a/contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs b/contracts/rekt-airdrop/src/reply.rs similarity index 93% rename from contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs rename to contracts/rekt-airdrop/src/reply.rs index d82588068..90f98d77b 100644 --- a/contracts/sg-eth-airdrop/src/dydx_airdrop/reply.rs +++ b/contracts/rekt-airdrop/src/reply.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] -use crate::dydx_airdrop::error::ContractError; -use crate::dydx_airdrop::state::CONFIG; +use crate::error::ContractError; +use crate::state::CONFIG; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, Reply}; use cw_utils::{parse_reply_instantiate_data, MsgInstantiateContractResponse, ParseReplyError}; diff --git a/contracts/sg-eth-airdrop/src/rekt_airdrop/state.rs b/contracts/rekt-airdrop/src/state.rs similarity index 100% rename from contracts/sg-eth-airdrop/src/rekt_airdrop/state.rs rename to contracts/rekt-airdrop/src/state.rs diff --git a/contracts/sg-eth-airdrop/src/lib.rs b/contracts/sg-eth-airdrop/src/lib.rs deleted file mode 100644 index 3abd8698a..000000000 --- a/contracts/sg-eth-airdrop/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod dydx_airdrop; -pub mod rekt_airdrop; diff --git a/scripts/publish-contracts.sh b/scripts/publish-contracts.sh index c6403e37b..d5088d262 100755 --- a/scripts/publish-contracts.sh +++ b/scripts/publish-contracts.sh @@ -32,6 +32,8 @@ cd contracts/minters/vending-minter-wl-flex && cargo publish && cd ../../.. sleep 15 cd contracts/minters/vending-minter-merkle-wl && cargo publish && cd ../../.. -cd contracts/sg-eth-airdrop && cargo publish && cd ../.. +cd contracts/rekt-airdrop && cargo publish && cd ../.. +sleep 15 +cd contracts/dxdy-airdrop && cargo publish && cd ../.. sleep 15 cd test-suite && cargo publish && cd .. diff --git a/scripts/schema.sh b/scripts/schema.sh index 3b9931704..31301eadc 100755 --- a/scripts/schema.sh +++ b/scripts/schema.sh @@ -30,7 +30,8 @@ for d in contracts/whitelists/*; do cd ../../.. fi done -cd contracts/sg-eth-airdrop && cargo schema && rm -rf schema/raw && cd ../.. +cd contracts/rekt-airdrop && cargo schema && rm -rf schema/raw && cd ../.. +cd contracts/dxdy-airdrop && cargo schema && rm -rf schema/raw && cd ../.. cd contracts/splits && cargo schema && rm -rf schema/raw && cd ../.. cd ts && yarn install && yarn codegen diff --git a/test-suite/Cargo.toml b/test-suite/Cargo.toml index 867d077f1..66ec4b125 100644 --- a/test-suite/Cargo.toml +++ b/test-suite/Cargo.toml @@ -44,7 +44,8 @@ sg721-updatable = { workspace = true } cw4-group = { workspace = true } sg-splits = { workspace = true } anyhow = "1.0.57" -sg-eth-airdrop = { workspace = true } +rekt-airdrop = { workspace = true } +dydx-airdrop = { workspace = true } whitelist-immutable = { workspace = true, features = ["library"] } cw721 = { workspace = true } cw721-base = { workspace = true, features = ["library"] } diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 2a19ef8e4..8bb27b3d7 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -123,11 +123,11 @@ pub fn contract_group() -> Box> { pub fn contract_eth_airdrop() -> Box> { let contract = ContractWrapper::new( - sg_eth_airdrop::rekt_airdrop::contract::execute, - sg_eth_airdrop::rekt_airdrop::contract::instantiate, - sg_eth_airdrop::rekt_airdrop::query::query, + rekt_airdrop::contract::execute, + rekt_airdrop::contract::instantiate, + rekt_airdrop::query::query, ) - .with_reply(sg_eth_airdrop::rekt_airdrop::reply::reply); + .with_reply(rekt_airdrop::reply::reply); Box::new(contract) } diff --git a/test-suite/src/sg_eth_airdrop.rs b/test-suite/src/dydx_airdrop.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop.rs rename to test-suite/src/dydx_airdrop.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs b/test-suite/src/dydx_airdrop/constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/dydx_airdrop.rs rename to test-suite/src/dydx_airdrop/constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/claim_constants.rs b/test-suite/src/dydx_airdrop/constants/claim_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/claim_constants.rs rename to test-suite/src/dydx_airdrop/constants/claim_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/collection_constants.rs b/test-suite/src/dydx_airdrop/constants/collection_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/dydx_airdrop/collection_constants.rs rename to test-suite/src/dydx_airdrop/constants/collection_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs b/test-suite/src/dydx_airdrop/setup.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop.rs rename to test-suite/src/dydx_airdrop/setup.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs similarity index 84% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs rename to test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs index ca0147aff..deb28a1f9 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/collection_whitelist_helpers.rs +++ b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs @@ -1,11 +1,7 @@ -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ - NATIVE_DENOM, STARGAZE_WALLET_01, -}; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::{ - MINT_PRICE, WHITELIST_AMOUNT, -}; +use crate::dydx_airdrop::constants::claim_constants::{NATIVE_DENOM, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::collection_constants::{MINT_PRICE, WHITELIST_AMOUNT}; -use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::execute_contract_with_msg; +use crate::dydx_airdrop::setup::execute_msg::execute_contract_with_msg; use cosmwasm_std::{coins, Addr}; use cw_multi_test::{BankSudo, Executor, SudoMsg}; use sg_multi_test::StargazeApp; @@ -58,7 +54,7 @@ pub fn execute_airdrop_claim( target_wallet: Addr, airdrop_contract: Addr, ) { - let claim_message = sg_eth_airdrop::dydx_airdrop::msg::ExecuteMsg::ClaimAirdrop { + let claim_message = dydx_airdrop::msg::ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str, eth_sig: eth_sig_str, }; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs b/test-suite/src/dydx_airdrop/setup/configure_mock_minter.rs similarity index 88% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs rename to test-suite/src/dydx_airdrop/setup/configure_mock_minter.rs index cfc9f32b9..f20e8acf1 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/configure_mock_minter.rs +++ b/test-suite/src/dydx_airdrop/setup/configure_mock_minter.rs @@ -5,8 +5,8 @@ use crate::common_setup::contract_boxes::contract_vending_factory; use crate::common_setup::setup_minter::vending_minter::mock_params::{ mock_create_minter, mock_params, }; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::CREATION_FEE; -use crate::sg_eth_airdrop::setup::dydx_airdrop::mock_minter_contract::mock_minter; +use crate::dydx_airdrop::constants::collection_constants::CREATION_FEE; +use crate::dydx_airdrop::setup::mock_minter_contract::mock_minter; use cosmwasm_std::{coins, Addr, Timestamp}; use cw_multi_test::Executor; use sg2::msg::Sg2ExecuteMsg; @@ -14,7 +14,7 @@ use sg2::tests::mock_collection_params_1; use sg_multi_test::StargazeApp; use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use crate::sg_eth_airdrop::setup::dydx_airdrop::mock_whitelist_contract::mock_whitelist; +use crate::dydx_airdrop::setup::mock_whitelist_contract::mock_whitelist; fn configure_mock_minter(app: &mut StargazeApp, creator: Addr) { let minter_code_id = app.store_code(mock_minter()); diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs b/test-suite/src/dydx_airdrop/setup/execute_msg.rs similarity index 88% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs rename to test-suite/src/dydx_airdrop/setup/execute_msg.rs index ba5e35a16..dc6162543 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/execute_msg.rs +++ b/test-suite/src/dydx_airdrop/setup/execute_msg.rs @@ -1,15 +1,15 @@ -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::OWNER; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::dydx_airdrop::constants::claim_constants::OWNER; +use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::{ common_setup::contract_boxes::{contract_eth_airdrop, contract_whitelist_immutable}, - sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams, + dydx_airdrop::setup::test_msgs::InstantiateParams, }; use anyhow::Error as anyhow_error; use cosmwasm_std::{coins, Addr}; use cw_multi_test::error::Error; use cw_multi_test::{AppResponse, BankSudo, Executor, SudoMsg}; +use dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg}; use eyre::Result; -use sg_eth_airdrop::dydx_airdrop::msg::{ExecuteMsg, InstantiateMsg}; use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_minter_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs similarity index 92% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_minter_contract.rs rename to test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs index a20daa8b6..97f35f899 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_minter_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs @@ -3,7 +3,7 @@ use cosmwasm_std::{ to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, }; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::rekt_airdrop::error::ContractError; +use dydx_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use vending_factory::msg::VendingMinterCreateMsg; use vending_minter::msg::{ExecuteMsg, QueryMsg}; @@ -67,6 +67,6 @@ fn query_config() -> ConfigResponse { } pub fn mock_minter() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query); - Box::new(contract) + let ract = ContractWrapper::new(execute, instantiate, query); + Box::new(ract) } diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_whitelist_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs similarity index 95% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_whitelist_contract.rs rename to test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs index 845fb96f7..6381e225c 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/mock_whitelist_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs @@ -1,7 +1,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::rekt_airdrop::error::ContractError; +use dydx_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use sg_whitelist::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs b/test-suite/src/dydx_airdrop/setup/setup_signatures.rs similarity index 91% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs rename to test-suite/src/dydx_airdrop/setup/setup_signatures.rs index 60ec889d1..488b4ccc5 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/setup_signatures.rs +++ b/test-suite/src/dydx_airdrop/setup/setup_signatures.rs @@ -1,4 +1,4 @@ -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::CONFIG_PLAINTEXT; +use crate::dydx_airdrop::constants::claim_constants::CONFIG_PLAINTEXT; use async_std::task; use ethers_core::{k256::ecdsa::SigningKey, rand::thread_rng, types::H160}; use ethers_signers::{LocalWallet, Signer, Wallet, WalletError}; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/test_msgs.rs b/test-suite/src/dydx_airdrop/setup/test_msgs.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/test_msgs.rs rename to test-suite/src/dydx_airdrop/setup/test_msgs.rs diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs b/test-suite/src/dydx_airdrop/tests.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/tests/dydx_airdrop.rs rename to test-suite/src/dydx_airdrop/tests.rs diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs similarity index 97% rename from test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs rename to test-suite/src/dydx_airdrop/tests/test_claim.rs index 58b6afeba..3a21fa870 100644 --- a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -1,28 +1,28 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::dydx_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::dydx_airdrop::setup_signatures::{ +use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; +use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::dydx_airdrop::setup::setup_signatures::{ get_msg_plaintext, get_signature, get_wallet_and_sig, }; -use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; +use crate::dydx_airdrop::setup::test_msgs::InstantiateParams; use async_std::task; use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; -use sg_eth_airdrop::dydx_airdrop::msg::{ExecuteMsg, QueryMsg}; +use dydx_airdrop::msg::{ExecuteMsg, QueryMsg}; use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ +use crate::dydx_airdrop::constants::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, }; -use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::{ +use crate::dydx_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, }; -use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; +use dydx_airdrop::contract::INSTANTIATION_FEE; fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minter_addr: Addr) { let query_msg = QueryMsg::GetMinter {}; diff --git a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs similarity index 83% rename from test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs rename to test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index b13aba8e8..3fd0b46f3 100644 --- a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,26 +1,22 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ - CONFIG_PLAINTEXT, STARGAZE_WALLET_01, -}; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::{ +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; -use crate::sg_eth_airdrop::setup::rekt_airdrop::collection_whitelist_helpers::{ +use crate::dydx_airdrop::setup::collection_whitelist_helpers::{ execute_airdrop_claim, execute_mint_fail_not_on_whitelist, execute_mint_success, send_funds_to_address, update_admin_for_whitelist, }; -use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::rekt_airdrop::setup_signatures::{ - get_msg_plaintext, get_wallet_and_sig, -}; -use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; +use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; +use crate::dydx_airdrop::setup::setup_signatures::{get_msg_plaintext, get_wallet_and_sig}; +use crate::dydx_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::rekt_airdrop::msg::QueryMsg; +use dydx_airdrop::msg::QueryMsg; use sg_std::GENESIS_MINT_START_TIME; extern crate whitelist_immutable; use crate::common_setup::templates::vending_minter_template; -use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; +use dydx_airdrop::contract::INSTANTIATION_FEE; #[test] fn test_set_minter_contract_success() { diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs similarity index 91% rename from test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs rename to test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index 6a23357d5..7be10686e 100644 --- a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -1,15 +1,15 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ +use crate::dydx_airdrop::constants::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, OWNER, }; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::dydx_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; +use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; +use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; +use crate::dydx_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; -use sg_eth_airdrop::dydx_airdrop::msg::QueryMsg; +use dydx_airdrop::contract::INSTANTIATION_FEE; +use dydx_airdrop::msg::QueryMsg; use whitelist_immutable::helpers::WhitelistImmutableContract; #[test] diff --git a/test-suite/src/lib.rs b/test-suite/src/lib.rs index 8747e00b4..1c489ae54 100644 --- a/test-suite/src/lib.rs +++ b/test-suite/src/lib.rs @@ -1,17 +1,18 @@ -pub mod common_setup; - #[cfg(test)] mod base_factory; #[cfg(test)] mod base_minter; +pub mod common_setup; +#[cfg(test)] +mod dydx_airdrop; #[cfg(test)] mod open_edition_factory; #[cfg(test)] mod open_edition_minter; #[cfg(test)] -mod sg721_base; +mod rekt_airdrop; #[cfg(test)] -mod sg_eth_airdrop; +mod sg721_base; #[cfg(test)] mod splits; #[cfg(test)] diff --git a/test-suite/src/rekt_airdrop.rs b/test-suite/src/rekt_airdrop.rs new file mode 100644 index 000000000..50d470eda --- /dev/null +++ b/test-suite/src/rekt_airdrop.rs @@ -0,0 +1,3 @@ +mod constants; +mod setup; +mod tests; diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs b/test-suite/src/rekt_airdrop/constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/rekt_airdrop.rs rename to test-suite/src/rekt_airdrop/constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs b/test-suite/src/rekt_airdrop/constants/claim_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/claim_constants.rs rename to test-suite/src/rekt_airdrop/constants/claim_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs b/test-suite/src/rekt_airdrop/constants/collection_constants.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/constants/rekt_airdrop/collection_constants.rs rename to test-suite/src/rekt_airdrop/constants/collection_constants.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs b/test-suite/src/rekt_airdrop/setup.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop.rs rename to test-suite/src/rekt_airdrop/setup.rs diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs b/test-suite/src/rekt_airdrop/setup/collection_whitelist_helpers.rs similarity index 84% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs rename to test-suite/src/rekt_airdrop/setup/collection_whitelist_helpers.rs index 486fe134a..6431396b2 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/collection_whitelist_helpers.rs +++ b/test-suite/src/rekt_airdrop/setup/collection_whitelist_helpers.rs @@ -1,11 +1,7 @@ -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ - NATIVE_DENOM, STARGAZE_WALLET_01, -}; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::{ - MINT_PRICE, WHITELIST_AMOUNT, -}; +use crate::rekt_airdrop::constants::claim_constants::{NATIVE_DENOM, STARGAZE_WALLET_01}; +use crate::rekt_airdrop::constants::collection_constants::{MINT_PRICE, WHITELIST_AMOUNT}; -use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::execute_contract_with_msg; +use crate::rekt_airdrop::setup::execute_msg::execute_contract_with_msg; use cosmwasm_std::{coins, Addr}; use cw_multi_test::{BankSudo, Executor, SudoMsg}; use sg_multi_test::StargazeApp; @@ -58,7 +54,7 @@ pub fn execute_airdrop_claim( target_wallet: Addr, airdrop_contract: Addr, ) { - let claim_message = sg_eth_airdrop::rekt_airdrop::msg::ExecuteMsg::ClaimAirdrop { + let claim_message = rekt_airdrop::msg::ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str, eth_sig: eth_sig_str, }; diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs b/test-suite/src/rekt_airdrop/setup/configure_mock_minter.rs similarity index 88% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs rename to test-suite/src/rekt_airdrop/setup/configure_mock_minter.rs index 66327e7af..ee456e191 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/configure_mock_minter.rs +++ b/test-suite/src/rekt_airdrop/setup/configure_mock_minter.rs @@ -5,8 +5,8 @@ use crate::common_setup::contract_boxes::contract_vending_factory; use crate::common_setup::setup_minter::vending_minter::mock_params::{ mock_create_minter, mock_params, }; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::CREATION_FEE; -use crate::sg_eth_airdrop::setup::rekt_airdrop::mock_minter_contract::mock_minter; +use crate::rekt_airdrop::constants::collection_constants::CREATION_FEE; +use crate::rekt_airdrop::setup::mock_minter_contract::mock_minter; use cosmwasm_std::{coins, Addr, Timestamp}; use cw_multi_test::Executor; use sg2::msg::Sg2ExecuteMsg; @@ -14,7 +14,7 @@ use sg2::tests::mock_collection_params_1; use sg_multi_test::StargazeApp; use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; -use crate::sg_eth_airdrop::setup::rekt_airdrop::mock_whitelist_contract::mock_whitelist; +use crate::rekt_airdrop::setup::mock_whitelist_contract::mock_whitelist; fn configure_mock_minter(app: &mut StargazeApp, creator: Addr) { let minter_code_id = app.store_code(mock_minter()); diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs b/test-suite/src/rekt_airdrop/setup/execute_msg.rs similarity index 88% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs rename to test-suite/src/rekt_airdrop/setup/execute_msg.rs index 47a681bc5..c0b4cd087 100644 --- a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/execute_msg.rs +++ b/test-suite/src/rekt_airdrop/setup/execute_msg.rs @@ -1,15 +1,15 @@ -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::OWNER; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; +use crate::rekt_airdrop::constants::claim_constants::OWNER; +use crate::rekt_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::{ common_setup::contract_boxes::{contract_eth_airdrop, contract_whitelist_immutable}, - sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams, + rekt_airdrop::setup::test_msgs::InstantiateParams, }; use anyhow::Error as anyhow_error; use cosmwasm_std::{coins, Addr}; use cw_multi_test::error::Error; use cw_multi_test::{AppResponse, BankSudo, Executor, SudoMsg}; use eyre::Result; -use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg}; +use rekt_airdrop::msg::{ExecuteMsg, InstantiateMsg}; use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs b/test-suite/src/rekt_airdrop/setup/mock_minter_contract.rs similarity index 92% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs rename to test-suite/src/rekt_airdrop/setup/mock_minter_contract.rs index a43d85d22..67ea729cd 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_minter_contract.rs +++ b/test-suite/src/rekt_airdrop/setup/mock_minter_contract.rs @@ -3,7 +3,7 @@ use cosmwasm_std::{ to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, }; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::dydx_airdrop::error::ContractError; +use rekt_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use vending_factory::msg::VendingMinterCreateMsg; use vending_minter::msg::{ExecuteMsg, QueryMsg}; @@ -67,6 +67,6 @@ fn query_config() -> ConfigResponse { } pub fn mock_minter() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query); - Box::new(contract) + let ract = ContractWrapper::new(execute, instantiate, query); + Box::new(ract) } diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs b/test-suite/src/rekt_airdrop/setup/mock_whitelist_contract.rs similarity index 95% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs rename to test-suite/src/rekt_airdrop/setup/mock_whitelist_contract.rs index 4e20f20ec..b0dc71a0f 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/mock_whitelist_contract.rs +++ b/test-suite/src/rekt_airdrop/setup/mock_whitelist_contract.rs @@ -1,7 +1,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; use cw_multi_test::{Contract, ContractWrapper}; -use sg_eth_airdrop::dydx_airdrop::error::ContractError; +use rekt_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; use sg_whitelist::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; diff --git a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs b/test-suite/src/rekt_airdrop/setup/setup_signatures.rs similarity index 91% rename from test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs rename to test-suite/src/rekt_airdrop/setup/setup_signatures.rs index 5e8c8f771..2df7771bb 100644 --- a/test-suite/src/sg_eth_airdrop/setup/dydx_airdrop/setup_signatures.rs +++ b/test-suite/src/rekt_airdrop/setup/setup_signatures.rs @@ -1,4 +1,4 @@ -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::CONFIG_PLAINTEXT; +use crate::rekt_airdrop::constants::claim_constants::CONFIG_PLAINTEXT; use async_std::task; use ethers_core::{k256::ecdsa::SigningKey, rand::thread_rng, types::H160}; use ethers_signers::{LocalWallet, Signer, Wallet, WalletError}; diff --git a/test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs b/test-suite/src/rekt_airdrop/setup/test_msgs.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/setup/rekt_airdrop/test_msgs.rs rename to test-suite/src/rekt_airdrop/setup/test_msgs.rs diff --git a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs b/test-suite/src/rekt_airdrop/tests.rs similarity index 100% rename from test-suite/src/sg_eth_airdrop/tests/rekt_airdrop.rs rename to test-suite/src/rekt_airdrop/tests.rs diff --git a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs b/test-suite/src/rekt_airdrop/tests/test_claim.rs similarity index 97% rename from test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs rename to test-suite/src/rekt_airdrop/tests/test_claim.rs index 85da99c7d..3bfd489cb 100644 --- a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_claim.rs +++ b/test-suite/src/rekt_airdrop/tests/test_claim.rs @@ -1,28 +1,28 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::rekt_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::rekt_airdrop::setup_signatures::{ +use crate::rekt_airdrop::constants::collection_constants::WHITELIST_AMOUNT; +use crate::rekt_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::rekt_airdrop::setup::setup_signatures::{ get_msg_plaintext, get_signature, get_wallet_and_sig, }; -use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; +use crate::rekt_airdrop::setup::test_msgs::InstantiateParams; use async_std::task; use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; -use sg_eth_airdrop::rekt_airdrop::msg::{ExecuteMsg, QueryMsg}; +use rekt_airdrop::msg::{ExecuteMsg, QueryMsg}; use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ +use crate::rekt_airdrop::constants::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, }; -use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::{ +use crate::rekt_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, }; -use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; +use rekt_airdrop::contract::INSTANTIATION_FEE; fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minter_addr: Addr) { let query_msg = QueryMsg::GetMinter {}; diff --git a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs b/test-suite/src/rekt_airdrop/tests/test_collection_whitelist.rs similarity index 83% rename from test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs rename to test-suite/src/rekt_airdrop/tests/test_collection_whitelist.rs index e90494170..ef071cb08 100644 --- a/test-suite/src/sg_eth_airdrop/tests/dydx_airdrop/test_collection_whitelist.rs +++ b/test-suite/src/rekt_airdrop/tests/test_collection_whitelist.rs @@ -1,26 +1,22 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::sg_eth_airdrop::constants::dydx_airdrop::claim_constants::{ - CONFIG_PLAINTEXT, STARGAZE_WALLET_01, -}; -use crate::sg_eth_airdrop::constants::dydx_airdrop::collection_constants::{ +use crate::rekt_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, STARGAZE_WALLET_01}; +use crate::rekt_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; -use crate::sg_eth_airdrop::setup::dydx_airdrop::collection_whitelist_helpers::{ +use crate::rekt_airdrop::setup::collection_whitelist_helpers::{ execute_airdrop_claim, execute_mint_fail_not_on_whitelist, execute_mint_success, send_funds_to_address, update_admin_for_whitelist, }; -use crate::sg_eth_airdrop::setup::dydx_airdrop::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::dydx_airdrop::setup_signatures::{ - get_msg_plaintext, get_wallet_and_sig, -}; -use crate::sg_eth_airdrop::setup::dydx_airdrop::test_msgs::InstantiateParams; +use crate::rekt_airdrop::setup::execute_msg::instantiate_contract; +use crate::rekt_airdrop::setup::setup_signatures::{get_msg_plaintext, get_wallet_and_sig}; +use crate::rekt_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::dydx_airdrop::msg::QueryMsg; +use rekt_airdrop::msg::QueryMsg; use sg_std::GENESIS_MINT_START_TIME; extern crate whitelist_immutable; use crate::common_setup::templates::vending_minter_template; -use sg_eth_airdrop::dydx_airdrop::contract::INSTANTIATION_FEE; +use rekt_airdrop::contract::INSTANTIATION_FEE; #[test] fn test_set_minter_contract_success() { diff --git a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs b/test-suite/src/rekt_airdrop/tests/test_immutable_whitelist.rs similarity index 91% rename from test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs rename to test-suite/src/rekt_airdrop/tests/test_immutable_whitelist.rs index f2e2a4e89..4b2ba72ed 100644 --- a/test-suite/src/sg_eth_airdrop/tests/rekt_airdrop/test_immutable_whitelist.rs +++ b/test-suite/src/rekt_airdrop/tests/test_immutable_whitelist.rs @@ -1,15 +1,15 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::sg_eth_airdrop::constants::rekt_airdrop::claim_constants::{ +use crate::rekt_airdrop::constants::claim_constants::{ CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, OWNER, }; -use crate::sg_eth_airdrop::constants::rekt_airdrop::collection_constants::WHITELIST_AMOUNT; -use crate::sg_eth_airdrop::setup::rekt_airdrop::configure_mock_minter::configure_mock_minter_with_mock_whitelist; -use crate::sg_eth_airdrop::setup::rekt_airdrop::execute_msg::instantiate_contract; -use crate::sg_eth_airdrop::setup::rekt_airdrop::test_msgs::InstantiateParams; +use crate::rekt_airdrop::constants::collection_constants::WHITELIST_AMOUNT; +use crate::rekt_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; +use crate::rekt_airdrop::setup::execute_msg::instantiate_contract; +use crate::rekt_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; -use sg_eth_airdrop::rekt_airdrop::contract::INSTANTIATION_FEE; -use sg_eth_airdrop::rekt_airdrop::msg::QueryMsg; +use rekt_airdrop::contract::INSTANTIATION_FEE; +use rekt_airdrop::msg::QueryMsg; use whitelist_immutable::helpers::WhitelistImmutableContract; #[test] diff --git a/test-suite/src/sg_eth_airdrop/constants.rs b/test-suite/src/sg_eth_airdrop/constants.rs deleted file mode 100644 index 3abd8698a..000000000 --- a/test-suite/src/sg_eth_airdrop/constants.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod dydx_airdrop; -pub mod rekt_airdrop; diff --git a/test-suite/src/sg_eth_airdrop/setup.rs b/test-suite/src/sg_eth_airdrop/setup.rs deleted file mode 100644 index 3abd8698a..000000000 --- a/test-suite/src/sg_eth_airdrop/setup.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod dydx_airdrop; -pub mod rekt_airdrop; diff --git a/test-suite/src/sg_eth_airdrop/tests.rs b/test-suite/src/sg_eth_airdrop/tests.rs deleted file mode 100644 index 3abd8698a..000000000 --- a/test-suite/src/sg_eth_airdrop/tests.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod dydx_airdrop; -pub mod rekt_airdrop; From b139dc63b2f7c7abc4d940f31542c57cf1dab2ff Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Mon, 29 Jan 2024 15:01:48 -0800 Subject: [PATCH 06/42] fix typo in wasm build --- .circleci/config.yml | 2 +- scripts/publish-contracts.sh | 2 +- scripts/schema.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2e7264036..15bdb238d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -570,7 +570,7 @@ jobs: echo "Compiling `basename $C`..." (cd $C && cargo build --release --lib --target wasm32-unknown-unknown --locked) done - for C in ./contracts/dxdy-airdrop/ + for C in ./contracts/dydx-airdrop/ do echo "Compiling `basename $C`..." (cd $C && cargo build --release --lib --target wasm32-unknown-unknown --locked) diff --git a/scripts/publish-contracts.sh b/scripts/publish-contracts.sh index d5088d262..dfd6ac58c 100755 --- a/scripts/publish-contracts.sh +++ b/scripts/publish-contracts.sh @@ -34,6 +34,6 @@ cd contracts/minters/vending-minter-merkle-wl && cargo publish && cd ../../.. cd contracts/rekt-airdrop && cargo publish && cd ../.. sleep 15 -cd contracts/dxdy-airdrop && cargo publish && cd ../.. +cd contracts/dydx-airdrop && cargo publish && cd ../.. sleep 15 cd test-suite && cargo publish && cd .. diff --git a/scripts/schema.sh b/scripts/schema.sh index 31301eadc..e028e4f60 100755 --- a/scripts/schema.sh +++ b/scripts/schema.sh @@ -31,7 +31,7 @@ for d in contracts/whitelists/*; do fi done cd contracts/rekt-airdrop && cargo schema && rm -rf schema/raw && cd ../.. -cd contracts/dxdy-airdrop && cargo schema && rm -rf schema/raw && cd ../.. +cd contracts/dydx-airdrop && cargo schema && rm -rf schema/raw && cd ../.. cd contracts/splits && cargo schema && rm -rf schema/raw && cd ../.. cd ts && yarn install && yarn codegen From aec674df90ad6ff1d52b83948c50efb57428a2a9 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Tue, 30 Jan 2024 17:57:25 +0300 Subject: [PATCH 07/42] Add name mint discount whitelist address --- contracts/dydx-airdrop/src/contract.rs | 1 + contracts/dydx-airdrop/src/msg.rs | 1 + contracts/dydx-airdrop/src/state.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index d6253bd32..056057b15 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -94,6 +94,7 @@ mod build_message { airdrop_amount: validate_airdrop_amount(msg.airdrop_amount)?, whitelist_address: None, minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, + name_discount_wl_address: deps.api.addr_validate(msg.name_discount_wl_address.as_ref())?, }) } } diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index cbf5ccdee..85d3845ef 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -10,6 +10,7 @@ pub struct InstantiateMsg { pub whitelist_code_id: u64, pub minter_address: Addr, pub per_address_limit: u32, + pub name_discount_wl_address: String, } #[cw_serde] diff --git a/contracts/dydx-airdrop/src/state.rs b/contracts/dydx-airdrop/src/state.rs index cefb96d81..42f99d8b8 100644 --- a/contracts/dydx-airdrop/src/state.rs +++ b/contracts/dydx-airdrop/src/state.rs @@ -10,6 +10,7 @@ pub struct Config { pub airdrop_amount: u128, pub whitelist_address: Option, pub minter_address: Addr, + pub name_discount_wl_address: Addr, } pub const CONFIG: Item = Item::new("cfg"); From dce9d179b8c61e27bdbb2dfde919f54ffe75b633 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Tue, 30 Jan 2024 17:58:52 +0300 Subject: [PATCH 08/42] Update tests to include name discount wl address --- test-suite/src/common_setup/contract_boxes.rs | 10 +++++++ .../dydx_airdrop/constants/claim_constants.rs | 1 + .../src/dydx_airdrop/setup/execute_msg.rs | 6 ++-- .../src/dydx_airdrop/setup/test_msgs.rs | 1 + .../src/dydx_airdrop/tests/test_claim.rs | 29 ++++++++++++++++--- .../tests/test_collection_whitelist.rs | 7 +++-- .../tests/test_immutable_whitelist.rs | 14 +++++++-- 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 8bb27b3d7..5a2eef181 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -131,6 +131,16 @@ pub fn contract_eth_airdrop() -> Box> { Box::new(contract) } +pub fn contract_dydx_airdrop() -> Box> { + let contract = ContractWrapper::new( + dydx_airdrop::contract::execute, + dydx_airdrop::contract::instantiate, + dydx_airdrop::query::query, + ) + .with_reply(dydx_airdrop::reply::reply); + Box::new(contract) +} + pub fn contract_whitelist_immutable() -> Box> { let contract = ContractWrapper::new( whitelist_immutable::contract::execute, diff --git a/test-suite/src/dydx_airdrop/constants/claim_constants.rs b/test-suite/src/dydx_airdrop/constants/claim_constants.rs index 674d66784..dc8f2a909 100644 --- a/test-suite/src/dydx_airdrop/constants/claim_constants.rs +++ b/test-suite/src/dydx_airdrop/constants/claim_constants.rs @@ -1,6 +1,7 @@ pub const OWNER: &str = "admin0001"; pub const MOCK_AIRDROP_ADDR_STR: &str = "contract3"; pub const MOCK_MINTER_ADDR_STR: &str = "contract1"; +pub const MOCK_NAME_DISCOUNT_WL_ADDR_STR: &str = "contract2"; pub const STARGAZE_WALLET_01: &str = "0xstargaze_wallet_01"; pub const STARGAZE_WALLET_02: &str = "0xstargaze_wallet_02"; pub const CONFIG_PLAINTEXT: &str = "My Stargaze address is {wallet} and I want a Winter Pal."; diff --git a/test-suite/src/dydx_airdrop/setup/execute_msg.rs b/test-suite/src/dydx_airdrop/setup/execute_msg.rs index dc6162543..e6f05c4b9 100644 --- a/test-suite/src/dydx_airdrop/setup/execute_msg.rs +++ b/test-suite/src/dydx_airdrop/setup/execute_msg.rs @@ -1,7 +1,7 @@ use crate::dydx_airdrop::constants::claim_constants::OWNER; use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::{ - common_setup::contract_boxes::{contract_eth_airdrop, contract_whitelist_immutable}, + common_setup::contract_boxes::{contract_dydx_airdrop, contract_whitelist_immutable}, dydx_airdrop::setup::test_msgs::InstantiateParams, }; use anyhow::Error as anyhow_error; @@ -31,9 +31,10 @@ pub fn instantiate_contract(params: InstantiateParams) -> Result Result { pub app: &'a mut StargazeApp, pub per_address_limit: u32, pub claim_msg_plaintext: String, + pub name_discount_wl_address: Addr, } diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index 3a21fa870..a08a0dd6c 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -13,10 +13,7 @@ use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::dydx_airdrop::constants::claim_constants::{ - CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, NATIVE_DENOM, OWNER, - STARGAZE_WALLET_01, STARGAZE_WALLET_02, -}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02}; use crate::dydx_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, @@ -37,6 +34,7 @@ fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minte fn test_instantiate() { let mut app = custom_mock_app(); let minter_address = Addr::unchecked("contract1"); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { @@ -48,6 +46,7 @@ fn test_instantiate() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); } @@ -57,6 +56,7 @@ fn test_instantiate_plaintext_too_long() { let long_config_plaintext: String = String::from_utf8(vec![b'X'; 1001]).unwrap() + " {wallet}"; let mut app = custom_mock_app(); let minter_address = Addr::unchecked("contract1"); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { @@ -68,6 +68,7 @@ fn test_instantiate_plaintext_too_long() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: long_config_plaintext, + name_discount_wl_address, }; let res = instantiate_contract(params).unwrap_err(); assert_eq!( @@ -81,6 +82,7 @@ fn test_instantiate_plaintext_missing_wallet() { let plaintext_config_no_wallet = "This message doesn't have wallet string".to_string(); let mut app = custom_mock_app(); let minter_address = Addr::unchecked("contract1"); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { @@ -92,6 +94,7 @@ fn test_instantiate_plaintext_missing_wallet() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: plaintext_config_no_wallet, + name_discount_wl_address, }; let res = instantiate_contract(params).unwrap_err(); assert_eq!( @@ -107,6 +110,7 @@ fn test_airdrop_eligible_query() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -118,6 +122,7 @@ fn test_airdrop_eligible_query() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); @@ -147,6 +152,7 @@ fn test_valid_eth_sig_claim() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -158,6 +164,7 @@ fn test_valid_eth_sig_claim() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); @@ -196,6 +203,7 @@ fn test_invalid_eth_sig_claim() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -207,6 +215,7 @@ fn test_invalid_eth_sig_claim() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); @@ -232,6 +241,7 @@ fn test_can_not_claim_twice() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -243,6 +253,7 @@ fn test_can_not_claim_twice() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); @@ -290,6 +301,7 @@ fn test_claim_one_valid_airdrop() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -297,6 +309,7 @@ fn test_claim_one_valid_airdrop() { funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_addr.clone(), + name_discount_wl_address: name_discount_wl_address.clone(), admin_account: Addr::unchecked(OWNER), app: &mut app, per_address_limit: 1, @@ -340,6 +353,7 @@ fn test_claim_twice_receive_funds_once() { configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -347,6 +361,7 @@ fn test_claim_twice_receive_funds_once() { funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_addr.clone(), + name_discount_wl_address: name_discount_wl_address.clone(), admin_account: Addr::unchecked(OWNER), app: &mut app, per_address_limit: 1, @@ -405,6 +420,7 @@ fn test_ineligible_does_not_receive_funds() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -416,6 +432,7 @@ fn test_ineligible_does_not_receive_funds() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); @@ -462,6 +479,7 @@ fn test_one_eth_claim_two_stargaze_addresses_invalid() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -473,6 +491,7 @@ fn test_one_eth_claim_two_stargaze_addresses_invalid() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); @@ -532,6 +551,7 @@ fn test_two_claims_allowed_success() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -543,6 +563,7 @@ fn test_two_claims_allowed_success() { app: &mut app, per_address_limit: 2, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address: name_discount_wl_address.clone(), }; instantiate_contract(params).unwrap(); diff --git a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index 3fd0b46f3..07e9f9658 100644 --- a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,6 +1,6 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01}; use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; @@ -23,7 +23,7 @@ fn test_set_minter_contract_success() { let vt = vending_minter_template(1); let (mut app, creator) = (vt.router, vt.accts.creator); let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); - + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); @@ -37,6 +37,7 @@ fn test_set_minter_contract_success() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); let airdrop_contract = Addr::unchecked("contract3"); @@ -53,6 +54,7 @@ fn test_claim_added_to_minter_whitelist() { let vt = vending_minter_template(1); let (mut app, creator, buyer) = (vt.router, vt.accts.creator, vt.accts.buyer); let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let whitelist_addr = configure_collection_whitelist(&mut app, creator.clone(), buyer, minter_addr.clone()); setup_block_time(&mut app, GENESIS_MINT_START_TIME, None); @@ -69,6 +71,7 @@ fn test_claim_added_to_minter_whitelist() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); diff --git a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index 7be10686e..d37346c90 100644 --- a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -1,7 +1,5 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::dydx_airdrop::constants::claim_constants::{ - CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, OWNER, -}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER}; use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; @@ -23,6 +21,7 @@ fn test_instantiate_with_addresses() { let mut app = { custom_mock_app }(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { @@ -34,6 +33,7 @@ fn test_instantiate_with_addresses() { app: &mut app, per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); @@ -67,6 +67,7 @@ fn test_whitelist_immutable_address_limit() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let params = InstantiateParams { addresses, @@ -77,6 +78,7 @@ fn test_whitelist_immutable_address_limit() { app: &mut app, per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); @@ -97,6 +99,7 @@ fn test_whitelist_immutable_address_count() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let params = InstantiateParams { addresses, @@ -107,6 +110,7 @@ fn test_whitelist_immutable_address_count() { app: &mut app, per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); @@ -127,6 +131,7 @@ fn test_whitelist_immutable_address_includes() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let params = InstantiateParams { addresses, @@ -137,6 +142,7 @@ fn test_whitelist_immutable_address_includes() { app: &mut app, per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); @@ -162,6 +168,7 @@ fn test_whitelist_immutable_address_config() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); let params = InstantiateParams { addresses, @@ -172,6 +179,7 @@ fn test_whitelist_immutable_address_config() { app: &mut app, per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); From e3a57c758498b7da55b53fca5d29c1bbe36c9ffa Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Thu, 22 Feb 2024 17:33:02 +0300 Subject: [PATCH 09/42] Add whitelist-immutable-flex & tests --- Cargo.lock | 18 ++ Cargo.toml | 1 + .../whitelist-immutable-flex/.cargo/config | 4 + .../whitelist-immutable-flex/.gitignore | 15 ++ .../whitelist-immutable-flex/Cargo.toml | 39 +++ .../examples/schema.rs | 11 + .../schema/whitelist-immutable.json | 206 ++++++++++++++++ .../whitelist-immutable-flex/src/contract.rs | 103 ++++++++ .../whitelist-immutable-flex/src/error.rs | 28 +++ .../whitelist-immutable-flex/src/helpers.rs | 45 ++++ .../whitelist-immutable-flex/src/lib.rs | 6 + .../whitelist-immutable-flex/src/msg.rs | 42 ++++ .../whitelist-immutable-flex/src/state.rs | 21 ++ test-suite/Cargo.toml | 1 + test-suite/src/common_setup/contract_boxes.rs | 9 + test-suite/src/lib.rs | 2 + test-suite/src/whitelist_immutable_flex.rs | 1 + .../src/whitelist_immutable_flex/tests.rs | 1 + .../tests/integration_tests.rs | 226 ++++++++++++++++++ 19 files changed, 779 insertions(+) create mode 100644 contracts/whitelists/whitelist-immutable-flex/.cargo/config create mode 100644 contracts/whitelists/whitelist-immutable-flex/.gitignore create mode 100644 contracts/whitelists/whitelist-immutable-flex/Cargo.toml create mode 100644 contracts/whitelists/whitelist-immutable-flex/examples/schema.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/schema/whitelist-immutable.json create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/contract.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/error.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/helpers.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/lib.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/msg.rs create mode 100644 contracts/whitelists/whitelist-immutable-flex/src/state.rs create mode 100644 test-suite/src/whitelist_immutable_flex.rs create mode 100644 test-suite/src/whitelist_immutable_flex/tests.rs create mode 100644 test-suite/src/whitelist_immutable_flex/tests/integration_tests.rs diff --git a/Cargo.lock b/Cargo.lock index 3861cfe09..755246ef6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4346,6 +4346,7 @@ dependencies = [ "vending-minter", "vending-minter-merkle-wl", "whitelist-immutable", + "whitelist-immutable-flex", "whitelist-mtree", ] @@ -5056,6 +5057,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "whitelist-immutable-flex" +version = "3.5.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.16.0", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "schemars", + "serde", + "sg-std", + "sg-whitelist", + "thiserror", +] + [[package]] name = "whitelist-mtree" version = "3.5.0" diff --git a/Cargo.toml b/Cargo.toml index 57fd87591..c8d5caa45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ vending-minter = { version = "3.5.0", path = "contracts/minters/vending-mi open-edition-factory = { version = "3.5.0", path = "contracts/factories/open-edition-factory" } open-edition-minter = { version = "3.5.0", path = "contracts/minters/open-edition-minter" } whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable" } +whitelist-immutable-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable-flex" } sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } rekt-airdrop = { version = "3.5.0", path = "contracts/rekt-airdrop"} diff --git a/contracts/whitelists/whitelist-immutable-flex/.cargo/config b/contracts/whitelists/whitelist-immutable-flex/.cargo/config new file mode 100644 index 000000000..ab407a024 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --example schema" diff --git a/contracts/whitelists/whitelist-immutable-flex/.gitignore b/contracts/whitelists/whitelist-immutable-flex/.gitignore new file mode 100644 index 000000000..dfdaaa6bc --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/.gitignore @@ -0,0 +1,15 @@ +# Build results +/target + +# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327) +.cargo-ok + +# Text file backups +**/*.rs.bk + +# macOS +.DS_Store + +# IDEs +*.iml +.idea diff --git a/contracts/whitelists/whitelist-immutable-flex/Cargo.toml b/contracts/whitelists/whitelist-immutable-flex/Cargo.toml new file mode 100644 index 000000000..7c4144f20 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "whitelist-immutable-flex" +authors = ["Michael S"] +description = "Store-once whitelist for read only use cases" +version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +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. + "contract.wasm", + "hash.txt", +] + +# 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] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw-controllers = "0.16.0" +cw2 = { workspace = true } +cw-utils = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +sg-whitelist = { workspace = true } +sg-std = { workspace = true } diff --git a/contracts/whitelists/whitelist-immutable-flex/examples/schema.rs b/contracts/whitelists/whitelist-immutable-flex/examples/schema.rs new file mode 100644 index 000000000..0ece61624 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/examples/schema.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::write_api; + +use whitelist_immutable_flex::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/contracts/whitelists/whitelist-immutable-flex/schema/whitelist-immutable.json b/contracts/whitelists/whitelist-immutable-flex/schema/whitelist-immutable.json new file mode 100644 index 000000000..6d9ae48ea --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/schema/whitelist-immutable.json @@ -0,0 +1,206 @@ +{ + "contract_name": "whitelist-immutable", + "contract_version": "3.5.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "addresses", + "per_address_limit" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + } + }, + "mint_discount_bps": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "per_address_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "type": "string", + "enum": [] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "includes_address" + ], + "properties": { + "includes_address": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "address_count" + ], + "properties": { + "address_count": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "per_address_limit" + ], + "properties": { + "per_address_limit": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "address_count": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "admin": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ConfigResponse", + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "$ref": "#/definitions/Config" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Config": { + "type": "object", + "required": [ + "admin", + "per_address_limit" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "mint_discount_bps": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "per_address_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } + }, + "includes_address": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" + }, + "per_address_limit": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PerAddressLimitResponse", + "type": "object", + "required": [ + "limit" + ], + "properties": { + "limit": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } +} diff --git a/contracts/whitelists/whitelist-immutable-flex/src/contract.rs b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs new file mode 100644 index 000000000..05118f024 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs @@ -0,0 +1,103 @@ +use crate::state::{Config, CONFIG, TOTAL_ADDRESS_COUNT, WHITELIST}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; +use cw2::set_contract_version; + +use crate::error::ContractError; +use crate::msg::{ConfigResponse, ExecuteMsg, InstantiateMsg, Member, QueryMsg}; +use cw_utils::nonpayable; +use sg_std::Response; + +// version info for migration info +const CONTRACT_NAME: &str = "crates.io:whitelist-immutable-flex"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + mut deps: DepsMut, + _env: Env, + info: MessageInfo, + mut msg: InstantiateMsg, +) -> Result { + nonpayable(&info)?; + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + let config = Config { + admin: info.sender, + mint_discount_bps: msg.mint_discount_bps, + }; + + msg.members.dedup(); + let count = update_whitelist(&mut deps, msg)?; + validate_nonempty_whitelist(count)?; + TOTAL_ADDRESS_COUNT.save(deps.storage, &count)?; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::default() + .add_attribute("action", "instantiate") + .add_attribute("contract_name", CONTRACT_NAME) + .add_attribute("contract_version", CONTRACT_VERSION)) +} + +fn update_whitelist(deps: &mut DepsMut, msg: InstantiateMsg) -> Result { + let mut count = 0u64; + for member in msg.members.into_iter() { + WHITELIST.save(deps.storage, &member.address, &member.mint_count)?; + count += 1; + } + Ok(count) +} + +fn validate_nonempty_whitelist(count: u64) -> Result { + if count < 1 { + return Err(ContractError::EmptyWhitelist {}); + } + Ok(true) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: ExecuteMsg, +) -> Result { + Ok(Response::new()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Config {} => to_json_binary(&query_config(deps)?), + QueryMsg::HasMember { address } => to_json_binary(&query_has_member(deps, address)?), + QueryMsg::Admin {} => to_json_binary(&query_admin(deps)?), + QueryMsg::AddressCount {} => to_json_binary(&query_address_count(deps)?), + QueryMsg::Member { address } => to_json_binary(&query_member(deps, address)?), + } +} + +pub fn query_config(deps: Deps) -> StdResult { + let config = CONFIG.load(deps.storage)?; + Ok(ConfigResponse { config }) +} + +pub fn query_has_member(deps: Deps, address: String) -> StdResult { + Ok(WHITELIST.has(deps.storage, &address)) +} + +pub fn query_admin(deps: Deps) -> StdResult { + let config = CONFIG.load(deps.storage)?; + Ok(config.admin.to_string()) +} + +pub fn query_address_count(deps: Deps) -> StdResult { + TOTAL_ADDRESS_COUNT.load(deps.storage) +} + +pub fn query_member(deps: Deps, address: String) -> StdResult { + let mint_count = WHITELIST.load(deps.storage, &address)?; + Ok(Member { + address, + mint_count, + }) +} diff --git a/contracts/whitelists/whitelist-immutable-flex/src/error.rs b/contracts/whitelists/whitelist-immutable-flex/src/error.rs new file mode 100644 index 000000000..9e7442933 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/error.rs @@ -0,0 +1,28 @@ +use cosmwasm_std::StdError; +use cw_utils::PaymentError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + PaymentError(#[from] PaymentError), + + #[error("Unauthorized")] + Unauthorized {}, + + #[error("AddressNotFound {addr}")] + AddressNotFound { addr: String }, + + #[error("OverPerAddressLimit")] + OverPerAddressLimit {}, + + #[error("AddressAlreadyExists {addr}")] + AddressAlreadyExists { addr: String }, + // Add any other custom errors you like here. + // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. + #[error("Empty whitelist, must provide at least one address")] + EmptyWhitelist {}, +} diff --git a/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs new file mode 100644 index 000000000..0d2dc6180 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs @@ -0,0 +1,45 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::{to_json_binary, Addr, QuerierWrapper, QueryRequest, StdResult, WasmQuery}; + +use crate::{ + msg::{ConfigResponse, QueryMsg}, + state::Config, +}; + +/// CwTemplateContract is a wrapper around Addr that provides a lot of helpers +/// for working with this. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct WhitelistImmutableFlexContract(pub Addr); + +impl WhitelistImmutableFlexContract { + pub fn addr(&self) -> Addr { + self.0.clone() + } + + pub fn includes(&self, querier: &QuerierWrapper, address: String) -> StdResult { + let includes: bool = querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.addr().into(), + msg: to_json_binary(&QueryMsg::HasMember { address })?, + }))?; + Ok(includes) + } + + pub fn address_count(&self, querier: &QuerierWrapper) -> StdResult { + let address_count: u64 = querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.addr().into(), + msg: to_json_binary(&QueryMsg::AddressCount {})?, + }))?; + Ok(address_count) + } + + pub fn config(&self, querier: &QuerierWrapper) -> StdResult { + let res: ConfigResponse = querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.addr().into(), + msg: to_json_binary(&QueryMsg::Config {})?, + }))?; + + Ok(res.config) + } +} diff --git a/contracts/whitelists/whitelist-immutable-flex/src/lib.rs b/contracts/whitelists/whitelist-immutable-flex/src/lib.rs new file mode 100644 index 000000000..0f47974b1 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/lib.rs @@ -0,0 +1,6 @@ +pub mod contract; +mod error; +pub mod helpers; +pub mod msg; +pub mod state; +pub use crate::error::ContractError; diff --git a/contracts/whitelists/whitelist-immutable-flex/src/msg.rs b/contracts/whitelists/whitelist-immutable-flex/src/msg.rs new file mode 100644 index 000000000..9342eede6 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/msg.rs @@ -0,0 +1,42 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; + +use crate::state::Config; + +#[cw_serde] +pub struct Member { + pub address: String, + pub mint_count: u32, +} +#[cw_serde] +pub struct InstantiateMsg { + pub members: Vec, + pub mint_discount_bps: Option, +} + +#[cw_serde] +pub enum ExecuteMsg {} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(ConfigResponse)] + Config {}, + #[returns(bool)] + HasMember { address: String }, + #[returns(MemberResponse)] + Member { address: String }, + #[returns(u64)] + Admin {}, + #[returns(u64)] + AddressCount {}, +} + +#[cw_serde] +pub struct ConfigResponse { + pub config: Config, +} + +#[cw_serde] +pub struct MemberResponse { + pub member: Member, +} diff --git a/contracts/whitelists/whitelist-immutable-flex/src/state.rs b/contracts/whitelists/whitelist-immutable-flex/src/state.rs new file mode 100644 index 000000000..ff078d849 --- /dev/null +++ b/contracts/whitelists/whitelist-immutable-flex/src/state.rs @@ -0,0 +1,21 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Decimal, Uint128}; +use cw_storage_plus::{Item, Map}; + +#[cw_serde] +pub struct Config { + pub admin: Addr, + pub mint_discount_bps: Option, +} + +impl Config { + pub fn mint_discount(&self) -> Option { + self.mint_discount_bps + .map(|v| Decimal::percent(v) / Uint128::from(100u128)) + } +} + +pub const CONFIG: Item = Item::new("config"); +pub const TOTAL_ADDRESS_COUNT: Item = Item::new("total_address_count"); +// Holds all addresses and mint count +pub const WHITELIST: Map<&str, u32> = Map::new("wl"); diff --git a/test-suite/Cargo.toml b/test-suite/Cargo.toml index 66ec4b125..99024d936 100644 --- a/test-suite/Cargo.toml +++ b/test-suite/Cargo.toml @@ -47,6 +47,7 @@ anyhow = "1.0.57" rekt-airdrop = { workspace = true } dydx-airdrop = { workspace = true } whitelist-immutable = { workspace = true, features = ["library"] } +whitelist-immutable-flex = { workspace = true, features = ["library"] } cw721 = { workspace = true } cw721-base = { workspace = true, features = ["library"] } sg2 = { workspace = true } diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 8bb27b3d7..fb61c551d 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -140,6 +140,15 @@ pub fn contract_whitelist_immutable() -> Box> { Box::new(contract) } +pub fn contract_whitelist_immutable_flex() -> Box> { + let contract = ContractWrapper::new( + whitelist_immutable_flex::contract::execute, + whitelist_immutable_flex::contract::instantiate, + whitelist_immutable_flex::contract::query, + ); + Box::new(contract) +} + pub fn contract_whitelist_merkletree() -> Box> { let contract = ContractWrapper::new( whitelist_mtree::contract::execute, diff --git a/test-suite/src/lib.rs b/test-suite/src/lib.rs index 1c489ae54..a50805fab 100644 --- a/test-suite/src/lib.rs +++ b/test-suite/src/lib.rs @@ -24,4 +24,6 @@ mod whitelist; #[cfg(test)] mod whitelist_immutable; #[cfg(test)] +mod whitelist_immutable_flex; +#[cfg(test)] mod whitelist_merkletree; diff --git a/test-suite/src/whitelist_immutable_flex.rs b/test-suite/src/whitelist_immutable_flex.rs new file mode 100644 index 000000000..14f00389d --- /dev/null +++ b/test-suite/src/whitelist_immutable_flex.rs @@ -0,0 +1 @@ +mod tests; diff --git a/test-suite/src/whitelist_immutable_flex/tests.rs b/test-suite/src/whitelist_immutable_flex/tests.rs new file mode 100644 index 000000000..07214813c --- /dev/null +++ b/test-suite/src/whitelist_immutable_flex/tests.rs @@ -0,0 +1 @@ +mod integration_tests; diff --git a/test-suite/src/whitelist_immutable_flex/tests/integration_tests.rs b/test-suite/src/whitelist_immutable_flex/tests/integration_tests.rs new file mode 100644 index 000000000..88f7f189e --- /dev/null +++ b/test-suite/src/whitelist_immutable_flex/tests/integration_tests.rs @@ -0,0 +1,226 @@ +#[cfg(test)] +mod tests { + use cosmwasm_std::Addr; + use cw_multi_test::Executor; + use sg_multi_test::StargazeApp; + use whitelist_immutable_flex::msg::*; + use whitelist_immutable_flex::{helpers::WhitelistImmutableFlexContract, state::Config}; + + use crate::common_setup::contract_boxes::{contract_whitelist_immutable_flex, custom_mock_app}; + + const CREATOR: &str = "creator"; + + fn get_init_address_list_1() -> Vec { + vec![ + Member { + address: "addr0001".to_string(), + mint_count: 1, + }, + Member { + address: "addr0002".to_string(), + mint_count: 2, + }, + Member { + address: "addr0003".to_string(), + mint_count: 3, + }, + Member { + address: "addr0004".to_string(), + mint_count: 4, + }, + Member { + address: "addr0005".to_string(), + mint_count: 5, + }, + ] + } + + fn get_init_address_list_2() -> Vec { + vec![ + Member { + address: "tester".to_string(), + mint_count: 1, + }, + Member { + address: "user".to_string(), + mint_count: 2, + }, + Member { + address: "random".to_string(), + mint_count: 3, + }, + Member { + address: "human".to_string(), + mint_count: 4, + }, + Member { + address: "bot".to_string(), + mint_count: 5, + }, + ] + } + + fn get_init_address_single_list() -> Vec { + vec![Member { + address: "onlyone".to_string(), + mint_count: 1, + }] + } + + pub fn instantiate_with_addresses(app: &mut StargazeApp, members: Vec) -> Addr { + let msg = InstantiateMsg { + members, + mint_discount_bps: None, + }; + let wl_id = app.store_code(contract_whitelist_immutable_flex()); + app.instantiate_contract( + wl_id, + Addr::unchecked(CREATOR), + &msg, + &[], + "wl-contract".to_string(), + None, + ) + .unwrap() + } + + pub fn query_address_count(app: &mut StargazeApp, addrs: Vec, wl_addr: Addr) { + let count: u64 = app + .wrap() + .query_wasm_smart(wl_addr, &QueryMsg::AddressCount {}) + .unwrap(); + assert_eq!(count, addrs.len() as u64); + } + + pub fn query_admin(app: &mut StargazeApp, wl_addr: Addr) { + let admin: String = app + .wrap() + .query_wasm_smart(wl_addr, &QueryMsg::Admin {}) + .unwrap(); + assert_eq!(admin, CREATOR.to_string()); + } + + pub fn query_includes_address(app: &mut StargazeApp, wl_addr: Addr, addr_to_check: String) { + let includes: bool = app + .wrap() + .query_wasm_smart( + wl_addr, + &QueryMsg::HasMember { + address: addr_to_check, + }, + ) + .unwrap(); + assert!(includes); + } + + pub fn query_member( + app: &mut StargazeApp, + wl_addr: Addr, + member_address: String, + expected_mint_count: u32, + ) { + let member: Member = app + .wrap() + .query_wasm_smart( + wl_addr, + &QueryMsg::Member { + address: member_address.clone(), + }, + ) + .unwrap(); + assert_eq!(member.address, member_address); + assert_eq!(member.mint_count, expected_mint_count); + } + #[test] + pub fn test_instantiate() { + let mut app = custom_mock_app(); + let addrs = get_init_address_list_2(); + let wl_addr = instantiate_with_addresses(&mut app, addrs.clone()); + let addr_to_check = addrs[1].clone().address; + query_admin(&mut app, wl_addr.clone()); + query_address_count(&mut app, addrs, wl_addr.clone()); + query_includes_address(&mut app, wl_addr.clone(), addr_to_check.clone()); + query_member(&mut app, wl_addr.clone(), addr_to_check, 2); + } + + #[test] + pub fn test_instantiate_single_list() { + let mut app = custom_mock_app(); + let addrs = get_init_address_single_list(); + let wl_addr = instantiate_with_addresses(&mut app, addrs.clone()); + let addr_to_check = addrs[0].clone().address; + query_admin(&mut app, wl_addr.clone()); + query_address_count(&mut app, addrs, wl_addr.clone()); + query_includes_address(&mut app, wl_addr.clone(), addr_to_check.clone()); + query_member(&mut app, wl_addr.clone(), addr_to_check, 1); + } + + #[test] + pub fn test_instantiate_empty_list_error() { + let mut app = custom_mock_app(); + let members = vec![]; + + let msg = InstantiateMsg { + members, + mint_discount_bps: None, + }; + let wl_id = app.store_code(contract_whitelist_immutable_flex()); + let res = app + .instantiate_contract( + wl_id, + Addr::unchecked(CREATOR), + &msg, + &[], + "wl-contract".to_string(), + None, + ) + .unwrap_err(); + let expected_error = "Empty whitelist, must provide at least one address"; + assert_eq!(res.root_cause().to_string(), expected_error) + } + + #[test] + pub fn test_helper_query_address_count() { + let mut app = custom_mock_app(); + let addrs = get_init_address_single_list(); + let wl_addr = instantiate_with_addresses(&mut app, addrs); + + let res: u64 = WhitelistImmutableFlexContract(wl_addr) + .address_count(&app.wrap()) + .unwrap(); + assert_eq!(res, 1); + } + + #[test] + pub fn test_helper_query_config() { + let mut app = custom_mock_app(); + let addrs = get_init_address_single_list(); + let wl_addr = instantiate_with_addresses(&mut app, addrs); + + let res: Config = WhitelistImmutableFlexContract(wl_addr) + .config(&app.wrap()) + .unwrap(); + let expected_config = Config { + admin: Addr::unchecked("creator"), + mint_discount_bps: None, + }; + assert_eq!(res, expected_config); + } + + #[test] + pub fn test_helper_query_includes() { + let mut app = custom_mock_app(); + let addrs = get_init_address_list_1(); + let wl_addr = instantiate_with_addresses(&mut app, addrs); + + let res: bool = WhitelistImmutableFlexContract(wl_addr.clone()) + .includes(&app.wrap(), "addr0003".to_string()) + .unwrap(); + assert!(res); + + let res: bool = WhitelistImmutableFlexContract(wl_addr) + .includes(&app.wrap(), "nonsense".to_string()) + .unwrap(); + assert!(!res); + } +} From 6c5efe8ea717b987a50ab5e26f17428e965ca427 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Thu, 22 Feb 2024 17:38:42 +0300 Subject: [PATCH 10/42] Address lint issues --- contracts/rekt-airdrop/src/contract.rs | 4 ++-- contracts/rekt-airdrop/src/query.rs | 6 +++--- .../src/dydx_airdrop/setup/mock_minter_contract.rs | 10 ++++------ .../src/dydx_airdrop/setup/mock_whitelist_contract.rs | 6 +++--- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/contracts/rekt-airdrop/src/contract.rs b/contracts/rekt-airdrop/src/contract.rs index 04c3b8982..5efbc570c 100644 --- a/contracts/rekt-airdrop/src/contract.rs +++ b/contracts/rekt-airdrop/src/contract.rs @@ -56,7 +56,7 @@ pub fn execute( mod build_message { use super::*; use crate::state::Config; - use cosmwasm_std::{to_binary, Deps, WasmMsg}; + use cosmwasm_std::{to_json_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; use whitelist_immutable::msg::InstantiateMsg as WGInstantiateMsg; @@ -78,7 +78,7 @@ mod build_message { admin: Some(env.contract.address.to_string()), funds: vec![], label: GENERIC_WHITELIST_LABEL.to_string(), - msg: to_binary(&whitelist_instantiate_msg)?, + msg: to_json_binary(&whitelist_instantiate_msg)?, }; Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) } diff --git a/contracts/rekt-airdrop/src/query.rs b/contracts/rekt-airdrop/src/query.rs index c3b50fcd1..d36a1aced 100644 --- a/contracts/rekt-airdrop/src/query.rs +++ b/contracts/rekt-airdrop/src/query.rs @@ -1,5 +1,5 @@ use crate::{msg::QueryMsg, state::CONFIG, ContractError}; -use cosmwasm_std::{entry_point, to_binary, Binary}; +use cosmwasm_std::{entry_point, to_json_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; use vending_minter::helpers::MinterContract; @@ -9,9 +9,9 @@ use whitelist_immutable::helpers::WhitelistImmutableContract; pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::AirdropEligible { eth_address } => { - to_binary(&query_airdrop_is_eligible(deps, eth_address)?) + to_json_binary(&query_airdrop_is_eligible(deps, eth_address)?) } - QueryMsg::GetMinter {} => to_binary(&query_minter(deps)?), + QueryMsg::GetMinter {} => to_json_binary(&query_minter(deps)?), } } diff --git a/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs index 97f35f899..c2b9123e0 100644 --- a/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs @@ -1,7 +1,5 @@ -use cosmwasm_std::entry_point; -use cosmwasm_std::{ - to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, -}; +use cosmwasm_std::{entry_point, to_json_binary}; +use cosmwasm_std::{Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp}; use cw_multi_test::{Contract, ContractWrapper}; use dydx_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; @@ -46,8 +44,8 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Config {} => to_binary(&query_config()), - _ => to_binary("invalid"), + QueryMsg::Config {} => to_json_binary(&query_config()), + _ => to_json_binary("invalid"), } } diff --git a/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs index 6381e225c..66566fe8b 100644 --- a/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs @@ -1,5 +1,5 @@ -use cosmwasm_std::entry_point; -use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; +use cosmwasm_std::{entry_point, to_json_binary}; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; use cw_multi_test::{Contract, ContractWrapper}; use dydx_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; @@ -31,7 +31,7 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult { - to_binary("mock") + to_json_binary("mock") } fn execute_add_members() -> Result { From f0616a4d15fb0c131bb4f08f01ae69a8b3761019 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Sun, 3 Mar 2024 13:23:29 +0800 Subject: [PATCH 11/42] using to_json_binary --- contracts/rekt-airdrop/src/contract.rs | 4 ++-- contracts/rekt-airdrop/src/query.rs | 6 +++--- test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs | 6 +++--- .../src/dydx_airdrop/setup/mock_whitelist_contract.rs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/rekt-airdrop/src/contract.rs b/contracts/rekt-airdrop/src/contract.rs index 04c3b8982..5efbc570c 100644 --- a/contracts/rekt-airdrop/src/contract.rs +++ b/contracts/rekt-airdrop/src/contract.rs @@ -56,7 +56,7 @@ pub fn execute( mod build_message { use super::*; use crate::state::Config; - use cosmwasm_std::{to_binary, Deps, WasmMsg}; + use cosmwasm_std::{to_json_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; use whitelist_immutable::msg::InstantiateMsg as WGInstantiateMsg; @@ -78,7 +78,7 @@ mod build_message { admin: Some(env.contract.address.to_string()), funds: vec![], label: GENERIC_WHITELIST_LABEL.to_string(), - msg: to_binary(&whitelist_instantiate_msg)?, + msg: to_json_binary(&whitelist_instantiate_msg)?, }; Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) } diff --git a/contracts/rekt-airdrop/src/query.rs b/contracts/rekt-airdrop/src/query.rs index c3b50fcd1..d36a1aced 100644 --- a/contracts/rekt-airdrop/src/query.rs +++ b/contracts/rekt-airdrop/src/query.rs @@ -1,5 +1,5 @@ use crate::{msg::QueryMsg, state::CONFIG, ContractError}; -use cosmwasm_std::{entry_point, to_binary, Binary}; +use cosmwasm_std::{entry_point, to_json_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; use vending_minter::helpers::MinterContract; @@ -9,9 +9,9 @@ use whitelist_immutable::helpers::WhitelistImmutableContract; pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::AirdropEligible { eth_address } => { - to_binary(&query_airdrop_is_eligible(deps, eth_address)?) + to_json_binary(&query_airdrop_is_eligible(deps, eth_address)?) } - QueryMsg::GetMinter {} => to_binary(&query_minter(deps)?), + QueryMsg::GetMinter {} => to_json_binary(&query_minter(deps)?), } } diff --git a/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs index 97f35f899..c6e0185c7 100644 --- a/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_minter_contract.rs @@ -1,6 +1,6 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, + to_json_binary, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult, Timestamp, }; use cw_multi_test::{Contract, ContractWrapper}; use dydx_airdrop::error::ContractError; @@ -46,8 +46,8 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Config {} => to_binary(&query_config()), - _ => to_binary("invalid"), + QueryMsg::Config {} => to_json_binary(&query_config()), + _ => to_json_binary("invalid"), } } diff --git a/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs index 6381e225c..c49840a93 100644 --- a/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs +++ b/test-suite/src/dydx_airdrop/setup/mock_whitelist_contract.rs @@ -1,5 +1,5 @@ use cosmwasm_std::entry_point; -use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdResult}; use cw_multi_test::{Contract, ContractWrapper}; use dydx_airdrop::error::ContractError; use sg_std::{Response, StargazeMsgWrapper}; @@ -31,7 +31,7 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult { - to_binary("mock") + to_json_binary("mock") } fn execute_add_members() -> Result { From 033e9b5d6ca390b477eec041dacba2df0f28b860 Mon Sep 17 00:00:00 2001 From: Humanalgorithm Date: Sun, 3 Mar 2024 14:37:15 +0800 Subject: [PATCH 12/42] fix lowercase conversion, add test, add assert --- contracts/dydx-airdrop/src/claim_airdrop.rs | 16 ++++- contracts/dydx-airdrop/src/error.rs | 3 + contracts/rekt-airdrop/src/claim_airdrop.rs | 16 ++++- contracts/rekt-airdrop/src/error.rs | 3 + .../whitelist-immutable/src/contract.rs | 3 +- .../src/dydx_airdrop/tests/test_claim.rs | 62 ++++++++++++++++++ .../src/rekt_airdrop/tests/test_claim.rs | 63 +++++++++++++++++++ 7 files changed, 161 insertions(+), 5 deletions(-) diff --git a/contracts/dydx-airdrop/src/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs index 7ac8d199a..fa486f030 100644 --- a/contracts/dydx-airdrop/src/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -19,15 +19,17 @@ pub fn claim_airdrop( eth_sig: String, ) -> Result { let config = CONFIG.load(deps.storage)?; + let eth_address_lower = eth_address.to_ascii_lowercase(); + validation::assert_lower_case(eth_address_lower.clone())?; validate_claim( &deps, info.clone(), - eth_address.clone(), + eth_address_lower.clone(), eth_sig, config.clone(), )?; let res = claim_and_whitelist_add(&deps, info, config.airdrop_amount)?; - increment_local_mint_count_for_address(deps, eth_address)?; + increment_local_mint_count_for_address(deps, eth_address_lower)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) } @@ -100,6 +102,15 @@ mod validation { ) } + pub fn assert_lower_case(eth_address: String) -> Result<(), ContractError> { + match eth_address.to_lowercase() == eth_address { + true => Ok(()), + false => Err(ContractError::EthAddressShouldBeLower { + address: eth_address, + }), + } + } + pub fn validate_claim( deps: &DepsMut, info: MessageInfo, @@ -107,6 +118,7 @@ mod validation { eth_sig: String, config: Config, ) -> Result<(), ContractError> { + assert_lower_case(eth_address.clone())?; validate_is_eligible(deps, eth_address.clone())?; validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; validate_mints_remaining(deps, ð_address)?; diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 67e7b7a64..4d99551f5 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -51,4 +51,7 @@ pub enum ContractError { #[error("Plaintext message is too long")] PlaintextTooLong {}, + + #[error("Address {address} should be converted to lowercase")] + EthAddressShouldBeLower { address: String }, } diff --git a/contracts/rekt-airdrop/src/claim_airdrop.rs b/contracts/rekt-airdrop/src/claim_airdrop.rs index 7ac8d199a..fa486f030 100644 --- a/contracts/rekt-airdrop/src/claim_airdrop.rs +++ b/contracts/rekt-airdrop/src/claim_airdrop.rs @@ -19,15 +19,17 @@ pub fn claim_airdrop( eth_sig: String, ) -> Result { let config = CONFIG.load(deps.storage)?; + let eth_address_lower = eth_address.to_ascii_lowercase(); + validation::assert_lower_case(eth_address_lower.clone())?; validate_claim( &deps, info.clone(), - eth_address.clone(), + eth_address_lower.clone(), eth_sig, config.clone(), )?; let res = claim_and_whitelist_add(&deps, info, config.airdrop_amount)?; - increment_local_mint_count_for_address(deps, eth_address)?; + increment_local_mint_count_for_address(deps, eth_address_lower)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) } @@ -100,6 +102,15 @@ mod validation { ) } + pub fn assert_lower_case(eth_address: String) -> Result<(), ContractError> { + match eth_address.to_lowercase() == eth_address { + true => Ok(()), + false => Err(ContractError::EthAddressShouldBeLower { + address: eth_address, + }), + } + } + pub fn validate_claim( deps: &DepsMut, info: MessageInfo, @@ -107,6 +118,7 @@ mod validation { eth_sig: String, config: Config, ) -> Result<(), ContractError> { + assert_lower_case(eth_address.clone())?; validate_is_eligible(deps, eth_address.clone())?; validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; validate_mints_remaining(deps, ð_address)?; diff --git a/contracts/rekt-airdrop/src/error.rs b/contracts/rekt-airdrop/src/error.rs index 67e7b7a64..4d99551f5 100644 --- a/contracts/rekt-airdrop/src/error.rs +++ b/contracts/rekt-airdrop/src/error.rs @@ -51,4 +51,7 @@ pub enum ContractError { #[error("Plaintext message is too long")] PlaintextTooLong {}, + + #[error("Address {address} should be converted to lowercase")] + EthAddressShouldBeLower { address: String }, } diff --git a/contracts/whitelists/whitelist-immutable/src/contract.rs b/contracts/whitelists/whitelist-immutable/src/contract.rs index dead0477a..c7940d696 100644 --- a/contracts/whitelists/whitelist-immutable/src/contract.rs +++ b/contracts/whitelists/whitelist-immutable/src/contract.rs @@ -44,7 +44,8 @@ pub fn instantiate( fn update_whitelist(deps: &mut DepsMut, msg: InstantiateMsg) -> Result { let mut count = 0u64; for address in msg.addresses.into_iter() { - WHITELIST.save(deps.storage, &address, &true)?; + let address_lower = address.clone().to_ascii_lowercase(); + WHITELIST.save(deps.storage, &address_lower, &true)?; count += 1; } Ok(count) diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index 3a21fa870..463386025 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -593,3 +593,65 @@ fn test_two_claims_allowed_success() { }]; assert_eq!(balances, expected_balance) } + +#[test] +fn test_claim_converts_to_lowercase() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let mut mixed_case = vec![]; + let mut to_upper = true; + for char in eth_addr_str.chars() { + if !to_upper { + mixed_case.extend([char.to_string().to_lowercase()]); + } else { + mixed_case.extend([char.to_string().to_uppercase()]); + } + to_upper = !to_upper; + } + let mixed_case_eth_addr: String = mixed_case.into_iter().collect(); + + let params = InstantiateParams { + addresses: vec![mixed_case_eth_addr.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: mixed_case_eth_addr, + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract, + ) + .unwrap(); + + let balances = app.wrap().query_all_balances(stargaze_wallet_01).unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance) +} diff --git a/test-suite/src/rekt_airdrop/tests/test_claim.rs b/test-suite/src/rekt_airdrop/tests/test_claim.rs index 3bfd489cb..8e5352823 100644 --- a/test-suite/src/rekt_airdrop/tests/test_claim.rs +++ b/test-suite/src/rekt_airdrop/tests/test_claim.rs @@ -39,6 +39,7 @@ fn test_instantiate() { let minter_address = Addr::unchecked("contract1"); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + let params = InstantiateParams { addresses: vec![eth_addr_str], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, @@ -593,3 +594,65 @@ fn test_two_claims_allowed_success() { }]; assert_eq!(balances, expected_balance) } + +#[test] +fn test_claim_converts_to_lowercase() { + let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); + let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); + + let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); + + let mut app = custom_mock_app(); + configure_mock_minter_with_mock_whitelist(&mut app); + let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); + + let mut mixed_case = vec![]; + let mut to_upper = true; + for char in eth_addr_str.chars() { + if !to_upper { + mixed_case.extend([char.to_string().to_lowercase()]); + } else { + mixed_case.extend([char.to_string().to_uppercase()]); + } + to_upper = !to_upper; + } + let mixed_case_eth_addr: String = mixed_case.into_iter().collect(); + + let params = InstantiateParams { + addresses: vec![mixed_case_eth_addr.clone()], + funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, + expected_airdrop_contract_id: 4, + minter_address: minter_addr.clone(), + admin_account: Addr::unchecked(OWNER), + app: &mut app, + per_address_limit: 1, + claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + }; + instantiate_contract(params).unwrap(); + query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + let balances = app + .wrap() + .query_all_balances(stargaze_wallet_01.clone()) + .unwrap(); + assert_eq!(balances, []); + + let claim_message = ExecuteMsg::ClaimAirdrop { + eth_address: mixed_case_eth_addr, + eth_sig: eth_sig_str, + }; + let _ = execute_contract_with_msg( + claim_message, + &mut app, + stargaze_wallet_01.clone(), + airdrop_contract, + ) + .unwrap(); + + let balances = app.wrap().query_all_balances(stargaze_wallet_01).unwrap(); + let expected_balance = [Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(WHITELIST_AMOUNT), + }]; + assert_eq!(balances, expected_balance) +} From 85a3e51873873b9c34c46307415ec9569cf2e63b Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Sun, 10 Mar 2024 13:53:28 +0300 Subject: [PATCH 13/42] Update instantiation to accommodate a whitelist-immutable-flex --- Cargo.lock | 2 +- contracts/dydx-airdrop/Cargo.toml | 2 +- contracts/dydx-airdrop/src/contract.rs | 11 +++++------ contracts/dydx-airdrop/src/msg.rs | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 755246ef6..41f913af2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1413,7 +1413,7 @@ dependencies = [ "thiserror", "vending-factory", "vending-minter", - "whitelist-immutable", + "whitelist-immutable-flex", ] [[package]] diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index 903f925ac..8cd5192cb 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -43,7 +43,7 @@ serde = { workspace = true } sg-std = { workspace = true } thiserror = { workspace = true } vending-minter = { workspace = true, features = ["library"] } -whitelist-immutable = { workspace = true, features = ["library"] } +whitelist-immutable-flex = { workspace = true, features = ["library"] } [dev-dependencies] async-std = "1.12.0" diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index 0e193633a..3abfb1189 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -59,25 +59,24 @@ mod build_message { use cosmwasm_std::{to_json_binary, Deps, WasmMsg}; use sg_std::{StargazeMsgWrapper, SubMsg}; use validation::validate_airdrop_amount; - use whitelist_immutable::msg::InstantiateMsg as WGInstantiateMsg; + use whitelist_immutable_flex::msg::InstantiateMsg as WIFInstantiateMsg; - pub const GENERIC_WHITELIST_LABEL: &str = "Generic Whitelist for Airdrop"; + pub const IMMUTABLE_WHITELIST_LABEL: &str = "Whitelist Immutable Flex for Airdrop"; pub const INIT_WHITELIST_REPLY_ID: u64 = 1; pub fn whitelist_instantiate( env: Env, msg: InstantiateMsg, ) -> Result, ContractError> { - let whitelist_instantiate_msg = WGInstantiateMsg { - addresses: msg.addresses, + let whitelist_instantiate_msg = WIFInstantiateMsg { + members: msg.members, mint_discount_bps: Some(0), - per_address_limit: msg.per_address_limit, }; let wasm_msg = WasmMsg::Instantiate { code_id: msg.whitelist_code_id, admin: Some(env.contract.address.to_string()), funds: vec![], - label: GENERIC_WHITELIST_LABEL.to_string(), + label: IMMUTABLE_WHITELIST_LABEL.to_string(), msg: to_json_binary(&whitelist_instantiate_msg)?, }; Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index 85d3845ef..06c49d6f5 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -1,15 +1,15 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Addr; +use whitelist_immutable_flex::msg::Member; #[cw_serde] pub struct InstantiateMsg { pub admin: Addr, pub claim_msg_plaintext: String, pub airdrop_amount: u128, - pub addresses: Vec, + pub members: Vec, pub whitelist_code_id: u64, pub minter_address: Addr, - pub per_address_limit: u32, pub name_discount_wl_address: String, } From 915228846770eab9ac789a1fdff622c144f293e9 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Sun, 10 Mar 2024 16:40:22 +0300 Subject: [PATCH 14/42] Use build_messages and validation as common crates for registration & claims --- contracts/dydx-airdrop/src/build_messages.rs | 41 +++++++ contracts/dydx-airdrop/src/validation.rs | 121 +++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 contracts/dydx-airdrop/src/build_messages.rs create mode 100644 contracts/dydx-airdrop/src/validation.rs diff --git a/contracts/dydx-airdrop/src/build_messages.rs b/contracts/dydx-airdrop/src/build_messages.rs new file mode 100644 index 000000000..b72abe8db --- /dev/null +++ b/contracts/dydx-airdrop/src/build_messages.rs @@ -0,0 +1,41 @@ +use cosmwasm_std::{Addr, BankMsg, coins, DepsMut, MessageInfo, StdResult}; +use sg_std::{CosmosMsg, NATIVE_DENOM, Response, SubMsg}; +use sg_whitelist::helpers::interface::CollectionWhitelistContract; +use sg_whitelist::msg::AddMembersMsg; +use crate::ContractError; +use crate::query::query_collection_whitelist; +use sg_whitelist::msg::ExecuteMsg as CollectionWhitelistExecuteMsg; + + +pub fn claim_and_whitelist_add( + deps: &DepsMut, + info: MessageInfo, + airdrop_amount: u128, +) -> Result { + let mut res = Response::new(); + let bank_msg = SubMsg::new(BankMsg::Send { + to_address: info.sender.to_string(), + amount: coins(airdrop_amount, NATIVE_DENOM), + }); + res = res.add_submessage(bank_msg); + let collection_whitelist = query_collection_whitelist(deps)?; + let res = res.add_message(add_member_to_collection_whitelist( + deps, + info.sender, + collection_whitelist, + )?); + Ok(res) +} + +fn add_member_to_collection_whitelist( + deps: &DepsMut, + wallet_address: Addr, + collection_whitelist: String, +) -> StdResult { + let inner_msg = AddMembersMsg { + to_add: vec![wallet_address.to_string()], + }; + let execute_msg = CollectionWhitelistExecuteMsg::AddMembers(inner_msg); + CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?) + .call(execute_msg) +} \ No newline at end of file diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs new file mode 100644 index 000000000..71b433112 --- /dev/null +++ b/contracts/dydx-airdrop/src/validation.rs @@ -0,0 +1,121 @@ +use cosmwasm_std::{DepsMut, MessageInfo, StdResult}; +use crate::ContractError; +use crate::state::{ADDRS_TO_MINT_COUNT}; +use crate::state::IS_ADDRESS_REGISTERED; + +use cosmwasm_std::StdError; +use ethereum_verify::verify_ethereum_text; + +use crate::{ + query::{query_airdrop_is_eligible, query_per_address_limit}, + state::Config, +}; + +pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { + str::replace( + &config.claim_msg_plaintext, + "{wallet}", + info.sender.as_ref(), + ) +} + +pub fn validate_registration( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, + eth_sig: String, + config: Config, +) -> Result<(), ContractError> { + validate_is_eligible(deps, eth_address.clone())?; + validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; + check_previous_registration(deps, ð_address)?; + Ok(()) +} + +pub fn validate_claim( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, + eth_sig: String, + config: Config, +) -> Result<(), ContractError> { + validate_is_eligible(deps, eth_address.clone())?; + validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; + validate_mints_remaining(deps, ð_address)?; + Ok(()) +} + +fn validate_is_eligible(deps: &DepsMut, eth_address: String) -> Result<(), ContractError> { + let eligible = query_airdrop_is_eligible(deps.as_ref(), eth_address.clone())?; + match eligible { + true => Ok(()), + false => Err(ContractError::AddressNotEligible { + address: eth_address, + }), + } +} + +fn validate_eth_sig( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, + eth_sig: String, + config: Config, +) -> Result<(), ContractError> { + let valid_eth_sig = + validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; + match valid_eth_sig { + true => Ok(()), + false => Err(ContractError::AddressNotEligible { + address: eth_address, + }), + } +} + +pub fn validate_mints_remaining( + deps: &DepsMut, + eth_address: &str, +) -> Result<(), ContractError> { + let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); + let mint_count = mint_count.unwrap_or(0); + let per_address_limit = query_per_address_limit(&deps.as_ref())?; + if mint_count < per_address_limit { + Ok(()) + } else { + Err(ContractError::MintCountReached { + address: eth_address.to_string(), + }) + } +} + +pub fn validate_ethereum_text( + deps: &DepsMut, + info: MessageInfo, + config: &Config, + eth_sig: String, + eth_address: String, +) -> StdResult { + let plaintext_msg = compute_plaintext_msg(config, info); + match hex::decode(eth_sig.clone()) { + Ok(eth_sig_hex) => { + verify_ethereum_text(deps.as_ref(), &plaintext_msg, ð_sig_hex, ð_address) + } + Err(_) => Err(StdError::InvalidHex { + msg: format!("Could not decode {eth_sig}"), + }), + } +} + +pub fn check_previous_registration( + deps: &DepsMut, + eth_address: &str, +) -> Result<(), ContractError> { + let registered = IS_ADDRESS_REGISTERED.load(deps.storage, eth_address).unwrap_or(false); + if registered { + Err(ContractError::AlreadyRegistered { + address: eth_address.to_string(), + }) + } else { + Ok(()) + } +} \ No newline at end of file From 83b114752cb7286390bb57ac166a3f3fc6e64a23 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Sun, 10 Mar 2024 17:59:26 +0300 Subject: [PATCH 15/42] Add mint_count query impl for whitelist-immutable-flex --- .../whitelists/whitelist-immutable-flex/src/helpers.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs index 0d2dc6180..7074b86d0 100644 --- a/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs +++ b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{to_json_binary, Addr, QuerierWrapper, QueryRequest, StdResult, WasmQuery}; +use crate::msg::{Member, MemberResponse}; use crate::{ msg::{ConfigResponse, QueryMsg}, state::Config, @@ -42,4 +43,13 @@ impl WhitelistImmutableFlexContract { Ok(res.config) } + + pub fn mint_count(&self, querier: &QuerierWrapper, address: String) -> StdResult { + let member_response: MemberResponse = + querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.addr().into(), + msg: to_json_binary(&QueryMsg::Member { address })?, + }))?; + Ok(member_response.member.mint_count) + } } From df428aa2b9f8dad68bed824536d682366460d73b Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Mon, 11 Mar 2024 18:05:33 +0300 Subject: [PATCH 16/42] Implement registration logic --- Cargo.lock | 171 ++++++++++++++++--- Cargo.toml | 1 + contracts/dydx-airdrop/Cargo.toml | 3 +- contracts/dydx-airdrop/src/build_messages.rs | 116 +++++++++++-- contracts/dydx-airdrop/src/claim_airdrop.rs | 145 +--------------- contracts/dydx-airdrop/src/contract.rs | 102 +---------- contracts/dydx-airdrop/src/error.rs | 3 + contracts/dydx-airdrop/src/lib.rs | 3 + contracts/dydx-airdrop/src/msg.rs | 4 + contracts/dydx-airdrop/src/query.rs | 22 ++- contracts/dydx-airdrop/src/register.rs | 26 +++ contracts/dydx-airdrop/src/state.rs | 1 + contracts/dydx-airdrop/src/validation.rs | 85 +++++++-- 13 files changed, 387 insertions(+), 295 deletions(-) create mode 100644 contracts/dydx-airdrop/src/register.rs diff --git a/Cargo.lock b/Cargo.lock index 41f913af2..85e11fd33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,7 +349,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "sg2", "thiserror", @@ -369,7 +369,7 @@ dependencies = [ "cw721-base 0.18.0", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "sg2", "sg4", @@ -1046,6 +1046,21 @@ dependencies = [ "cosmwasm-std", ] +[[package]] +name = "cw-controllers" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3ababe9f0a473c2d878b7c973eee08e05e5d768253fbb08d475daeadba503" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "cw-utils 0.15.1", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "cw-controllers" version = "0.16.0" @@ -1121,6 +1136,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cw-storage-plus" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "cw-storage-plus" version = "0.16.0" @@ -1143,6 +1169,21 @@ dependencies = [ "serde", ] +[[package]] +name = "cw-utils" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.15.1", + "schemars", + "semver", + "serde", + "thiserror", +] + [[package]] name = "cw-utils" version = "0.16.0" @@ -1173,6 +1214,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "schemars", + "serde", +] + [[package]] name = "cw2" version = "0.16.0" @@ -1403,8 +1457,8 @@ dependencies = [ "schemars", "serde", "sg-multi-test", - "sg-std", - "sg-whitelist", + "sg-std 3.2.0", + "sg-whitelist-flex", "sg1", "sg2", "sg721-base", @@ -1414,6 +1468,7 @@ dependencies = [ "vending-factory", "vending-minter", "whitelist-immutable-flex", + "whitelist-updatable", ] [[package]] @@ -2615,7 +2670,7 @@ dependencies = [ "cw2 1.1.2", "semver", "sg-metadata", - "sg-std", + "sg-std 3.2.0", "sg1", "sg2", "sg721", @@ -2636,7 +2691,7 @@ dependencies = [ "semver", "serde", "sg-metadata", - "sg-std", + "sg-std 3.2.0", "sg1", "sg2", "sg4", @@ -3194,7 +3249,7 @@ dependencies = [ "schemars", "serde", "sg-multi-test", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "sg1", "sg2", @@ -3685,7 +3740,7 @@ dependencies = [ "cw-utils 1.0.3", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "thiserror", ] @@ -3709,7 +3764,7 @@ dependencies = [ "serde", "sg-controllers", "sg-mint-hooks-derive", - "sg-std", + "sg-std 3.2.0", "thiserror", ] @@ -3734,7 +3789,20 @@ dependencies = [ "cw-multi-test", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", +] + +[[package]] +name = "sg-name-minter" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec03766b92b4999ebd9b2f6f10a379345db105c3361d132abd606d64c4a4d73" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.15.1", + "schemars", + "serde", ] [[package]] @@ -3751,7 +3819,22 @@ dependencies = [ "schemars", "serde", "sg-controllers", - "sg-std", + "sg-std 3.2.0", + "thiserror", +] + +[[package]] +name = "sg-std" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f332c16bb8cab94613e6b9bef76fbd27937e0be1c40c979ed1a7367b96866126" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "cw721 0.16.0", + "schemars", + "serde", "thiserror", ] @@ -3782,11 +3865,23 @@ dependencies = [ "rust_decimal", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "thiserror", ] +[[package]] +name = "sg-whitelist-basic" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0670b0de4489224faa3c18ceb28af7251441118473f454110739a69df587b9" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "sg-whitelist-flex" version = "3.5.0" @@ -3799,7 +3894,7 @@ dependencies = [ "rust_decimal", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "thiserror", ] @@ -3811,7 +3906,7 @@ dependencies = [ "cosmwasm-std", "cw-utils 1.0.3", "serde", - "sg-std", + "sg-std 3.2.0", "thiserror", ] @@ -3867,7 +3962,7 @@ dependencies = [ "cw721 0.18.0", "cw721-base 0.18.0", "serde", - "sg-std", + "sg-std 3.2.0", "sg721", "thiserror", "url", @@ -3886,7 +3981,7 @@ dependencies = [ "schemars", "serde", "sg-metadata", - "sg-std", + "sg-std 3.2.0", "sg721", "sg721-base", ] @@ -3903,7 +3998,7 @@ dependencies = [ "cw721-base 0.18.0", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg721", "sg721-base", ] @@ -3923,7 +4018,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "sg721", "sg721-base", @@ -4329,7 +4424,7 @@ dependencies = [ "sg-metadata", "sg-multi-test", "sg-splits", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "sg1", "sg2", @@ -4755,7 +4850,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg1", "sg2", "sg721", @@ -4778,7 +4873,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "sg1", "sg2", @@ -4807,7 +4902,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "sg1", "sg2", @@ -4836,7 +4931,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "sg1", "sg2", @@ -4866,7 +4961,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist-flex", "sg1", "sg2", @@ -4895,7 +4990,7 @@ dependencies = [ "schemars", "semver", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist-flex", "sg1", "sg2", @@ -5052,7 +5147,7 @@ dependencies = [ "cw2 1.1.2", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "thiserror", ] @@ -5069,7 +5164,7 @@ dependencies = [ "cw2 1.1.2", "schemars", "serde", - "sg-std", + "sg-std 3.2.0", "sg-whitelist", "thiserror", ] @@ -5089,12 +5184,32 @@ dependencies = [ "schemars", "serde", "serde_json", - "sg-std", + "sg-std 3.2.0", "sg1", "thiserror", "url", ] +[[package]] +name = "whitelist-updatable" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266929a317b6b0b09f421bb5a478e4d1377d1637927f59bf76b21b05352fcbd1" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.16.0", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "schemars", + "serde", + "sg-name-minter", + "sg-std 0.21.12", + "sg-whitelist-basic", + "thiserror", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index c8d5caa45..6526185ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ open-edition-factory = { version = "3.5.0", path = "contracts/factories/open-edi open-edition-minter = { version = "3.5.0", path = "contracts/minters/open-edition-minter" } whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable" } whitelist-immutable-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable-flex" } +whitelist-updatable = "0.12.0" sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } rekt-airdrop = { version = "3.5.0", path = "contracts/rekt-airdrop"} diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index 8cd5192cb..7068bb8e4 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -34,7 +34,7 @@ cw2 = { workspace = true } ethereum-verify = { workspace = true } hex = "0.4" rust_decimal = { version = "1.14.3" } -sg-whitelist = { workspace = true } +sg-whitelist-flex = { workspace = true } sg1 = { workspace = true } sha2 = { workspace = true } sha3 = "0.10" @@ -44,6 +44,7 @@ sg-std = { workspace = true } thiserror = { workspace = true } vending-minter = { workspace = true, features = ["library"] } whitelist-immutable-flex = { workspace = true, features = ["library"] } +whitelist-updatable = { workspace = true, features = ["library"] } [dev-dependencies] async-std = "1.12.0" diff --git a/contracts/dydx-airdrop/src/build_messages.rs b/contracts/dydx-airdrop/src/build_messages.rs index b72abe8db..5ddf5a99d 100644 --- a/contracts/dydx-airdrop/src/build_messages.rs +++ b/contracts/dydx-airdrop/src/build_messages.rs @@ -1,28 +1,96 @@ -use cosmwasm_std::{Addr, BankMsg, coins, DepsMut, MessageInfo, StdResult}; -use sg_std::{CosmosMsg, NATIVE_DENOM, Response, SubMsg}; -use sg_whitelist::helpers::interface::CollectionWhitelistContract; -use sg_whitelist::msg::AddMembersMsg; +use cosmwasm_std::{Addr, BankMsg, coins, Deps, DepsMut, Env, MessageInfo, StdResult, to_json_binary, WasmMsg}; +use sg_std::{CosmosMsg, NATIVE_DENOM, Response, StargazeMsgWrapper, SubMsg}; +use whitelist_updatable::msg::ExecuteMsg; +// TODO: Replace with whitelist_updatable_flatrate +use whitelist_updatable::msg::ExecuteMsg::AddAddresses; +use sg_whitelist_flex::helpers::interface::CollectionWhitelistContract; use crate::ContractError; -use crate::query::query_collection_whitelist; -use sg_whitelist::msg::ExecuteMsg as CollectionWhitelistExecuteMsg; +use crate::query::{query_collection_whitelist, query_mint_count}; +use sg_whitelist_flex::msg::{ExecuteMsg as CollectionWhitelistExecuteMsg, Member}; +use sg_whitelist_flex::msg::AddMembersMsg; +use crate::msg::InstantiateMsg; +use crate::state::{CONFIG, Config}; +use whitelist_immutable_flex::msg::InstantiateMsg as WIFInstantiateMsg; +pub const IMMUTABLE_WHITELIST_LABEL: &str = "Whitelist Immutable Flex for Airdrop"; +pub const INIT_WHITELIST_REPLY_ID: u64 = 1; +pub fn whitelist_instantiate( + env: Env, + msg: InstantiateMsg, +) -> Result, ContractError> { + let whitelist_instantiate_msg = WIFInstantiateMsg { + members: msg.members, + mint_discount_bps: Some(0), + }; + let wasm_msg = WasmMsg::Instantiate { + code_id: msg.whitelist_code_id, + admin: Some(env.contract.address.to_string()), + funds: vec![], + label: IMMUTABLE_WHITELIST_LABEL.to_string(), + msg: to_json_binary(&whitelist_instantiate_msg)?, + }; + Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) +} -pub fn claim_and_whitelist_add( - deps: &DepsMut, +pub fn state_config( + deps: Deps, + info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + Ok(Config { + admin: info.sender, + claim_msg_plaintext: msg.clone().claim_msg_plaintext, + airdrop_amount: crate::validation::validate_airdrop_amount(msg.airdrop_amount)?, + whitelist_address: None, + minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, + name_discount_wl_address: deps.api.addr_validate(msg.name_discount_wl_address.as_ref())?, + }) +} + +pub fn claim_reward( info: MessageInfo, airdrop_amount: u128, ) -> Result { + // TODO: add a limit to the number of claims (500 as per the proposal) let mut res = Response::new(); let bank_msg = SubMsg::new(BankMsg::Send { to_address: info.sender.to_string(), amount: coins(airdrop_amount, NATIVE_DENOM), }); res = res.add_submessage(bank_msg); + + Ok(res) +} + +pub fn dust_and_whitelist_add( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, +) -> Result { + let res = add_member_to_whitelists(deps, info.clone(), eth_address)?; + let res = res.add_message(dust_member_wallet(info.clone())?); + Ok(res) +} +pub fn add_member_to_whitelists( + deps: &DepsMut, + info: MessageInfo, + eth_address: String, +) -> Result { + let config = CONFIG.load(deps.storage)?; let collection_whitelist = query_collection_whitelist(deps)?; + let mint_count = query_mint_count(deps, eth_address.clone())?; + let names_discount_whitelist = config.name_discount_wl_address; + + let res = Response::new(); let res = res.add_message(add_member_to_collection_whitelist( deps, - info.sender, + info.sender.clone(), collection_whitelist, + mint_count, + )?); + let res = res.add_message(add_member_to_names_discount_whitelist( + info.sender.clone(), + names_discount_whitelist.clone().to_string(), )?); Ok(res) } @@ -31,11 +99,39 @@ fn add_member_to_collection_whitelist( deps: &DepsMut, wallet_address: Addr, collection_whitelist: String, + mint_count: u32, ) -> StdResult { let inner_msg = AddMembersMsg { - to_add: vec![wallet_address.to_string()], + to_add: vec![Member { + address: wallet_address.to_string(), + mint_count, + }], }; let execute_msg = CollectionWhitelistExecuteMsg::AddMembers(inner_msg); CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?) .call(execute_msg) +} + +fn add_member_to_names_discount_whitelist( + wallet_address: Addr, + name_discount_wl: String, +) -> StdResult { + let execute_msg: ExecuteMsg = AddAddresses { addresses: vec![wallet_address.to_string()] }; + let msg = to_json_binary(&execute_msg)?; + Ok(WasmMsg::Execute { + contract_addr: name_discount_wl, + msg, + funds: vec![], + } + .into()) +} + +pub fn dust_member_wallet( + info: MessageInfo, +) -> StdResult { + let inner_msg = BankMsg::Send { + to_address: info.sender.to_string(), + amount: coins(1000000, NATIVE_DENOM), + }; + Ok(CosmosMsg::Bank(inner_msg)) } \ No newline at end of file diff --git a/contracts/dydx-airdrop/src/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs index 7ac8d199a..131235265 100644 --- a/contracts/dydx-airdrop/src/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -1,15 +1,11 @@ -use crate::query::query_collection_whitelist; use crate::state::ADDRS_TO_MINT_COUNT; use crate::{state::CONFIG, ContractError}; -use build_messages::claim_and_whitelist_add; use cosmwasm_std::DepsMut; -use cosmwasm_std::{coins, Addr, BankMsg, StdResult}; use cosmwasm_std::{Env, MessageInfo}; use sg_std::Response; -use sg_std::{CosmosMsg, SubMsg}; -use sg_whitelist::msg::ExecuteMsg as CollectionWhitelistExecuteMsg; -use sg_whitelist::{helpers::interface::CollectionWhitelistContract, msg::AddMembersMsg}; -use validation::validate_claim; +use crate::build_messages::{claim_reward}; + +use crate::validation::validate_claim; pub fn claim_airdrop( deps: DepsMut, @@ -26,7 +22,9 @@ pub fn claim_airdrop( eth_sig, config.clone(), )?; - let res = claim_and_whitelist_add(&deps, info, config.airdrop_amount)?; + let res = claim_reward(info, config.airdrop_amount)?; + + // TODO: To be removed increment_local_mint_count_for_address(deps, eth_address)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) @@ -43,134 +41,3 @@ pub fn increment_local_mint_count_for_address( Ok(Response::new()) } - -mod build_messages { - use super::*; - use sg_std::NATIVE_DENOM; - - pub fn claim_and_whitelist_add( - deps: &DepsMut, - info: MessageInfo, - airdrop_amount: u128, - ) -> Result { - let mut res = Response::new(); - let bank_msg = SubMsg::new(BankMsg::Send { - to_address: info.sender.to_string(), - amount: coins(airdrop_amount, NATIVE_DENOM), - }); - res = res.add_submessage(bank_msg); - let collection_whitelist = query_collection_whitelist(deps)?; - let res = res.add_message(add_member_to_collection_whitelist( - deps, - info.sender, - collection_whitelist, - )?); - Ok(res) - } - - fn add_member_to_collection_whitelist( - deps: &DepsMut, - wallet_address: Addr, - collection_whitelist: String, - ) -> StdResult { - let inner_msg = AddMembersMsg { - to_add: vec![wallet_address.to_string()], - }; - let execute_msg = CollectionWhitelistExecuteMsg::AddMembers(inner_msg); - CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?) - .call(execute_msg) - } -} - -mod validation { - use super::*; - use cosmwasm_std::StdError; - use ethereum_verify::verify_ethereum_text; - - use crate::{ - query::{query_airdrop_is_eligible, query_per_address_limit}, - state::Config, - }; - - pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { - str::replace( - &config.claim_msg_plaintext, - "{wallet}", - info.sender.as_ref(), - ) - } - - pub fn validate_claim( - deps: &DepsMut, - info: MessageInfo, - eth_address: String, - eth_sig: String, - config: Config, - ) -> Result<(), ContractError> { - validate_is_eligible(deps, eth_address.clone())?; - validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; - validate_mints_remaining(deps, ð_address)?; - Ok(()) - } - - fn validate_is_eligible(deps: &DepsMut, eth_address: String) -> Result<(), ContractError> { - let eligible = query_airdrop_is_eligible(deps.as_ref(), eth_address.clone())?; - match eligible { - true => Ok(()), - false => Err(ContractError::AddressNotEligible { - address: eth_address, - }), - } - } - - fn validate_eth_sig( - deps: &DepsMut, - info: MessageInfo, - eth_address: String, - eth_sig: String, - config: Config, - ) -> Result<(), ContractError> { - let valid_eth_sig = - validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; - match valid_eth_sig { - true => Ok(()), - false => Err(ContractError::AddressNotEligible { - address: eth_address, - }), - } - } - - pub fn validate_mints_remaining( - deps: &DepsMut, - eth_address: &str, - ) -> Result<(), ContractError> { - let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); - let mint_count = mint_count.unwrap_or(0); - let per_address_limit = query_per_address_limit(&deps.as_ref())?; - if mint_count < per_address_limit { - Ok(()) - } else { - Err(ContractError::MintCountReached { - address: eth_address.to_string(), - }) - } - } - - pub fn validate_ethereum_text( - deps: &DepsMut, - info: MessageInfo, - config: &Config, - eth_sig: String, - eth_address: String, - ) -> StdResult { - let plaintext_msg = compute_plaintext_msg(config, info); - match hex::decode(eth_sig.clone()) { - Ok(eth_sig_hex) => { - verify_ethereum_text(deps.as_ref(), &plaintext_msg, ð_sig_hex, ð_address) - } - Err(_) => Err(StdError::InvalidHex { - msg: format!("Could not decode {eth_sig}"), - }), - } - } -} diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index 3abfb1189..5c4f673e4 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -10,8 +10,9 @@ use cw2::set_contract_version; use sg1::fair_burn; use sg_std::Response; -use build_message::{state_config, whitelist_instantiate}; -use validation::validate_instantiation_params; +use crate::build_messages::{state_config, whitelist_instantiate}; +use crate::register::register; +use crate::validation::validate_instantiation_params; const CONTRACT_NAME: &str = "crates.io:dydx-airdrop"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -46,102 +47,13 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { match msg { + ExecuteMsg::Register { + eth_address, + eth_sig, + } => register(deps, info, _env, eth_address, eth_sig), ExecuteMsg::ClaimAirdrop { eth_address, eth_sig, } => claim_airdrop(deps, info, _env, eth_address, eth_sig), } } - -mod build_message { - use super::*; - use crate::state::Config; - use cosmwasm_std::{to_json_binary, Deps, WasmMsg}; - use sg_std::{StargazeMsgWrapper, SubMsg}; - use validation::validate_airdrop_amount; - use whitelist_immutable_flex::msg::InstantiateMsg as WIFInstantiateMsg; - - pub const IMMUTABLE_WHITELIST_LABEL: &str = "Whitelist Immutable Flex for Airdrop"; - pub const INIT_WHITELIST_REPLY_ID: u64 = 1; - - pub fn whitelist_instantiate( - env: Env, - msg: InstantiateMsg, - ) -> Result, ContractError> { - let whitelist_instantiate_msg = WIFInstantiateMsg { - members: msg.members, - mint_discount_bps: Some(0), - }; - let wasm_msg = WasmMsg::Instantiate { - code_id: msg.whitelist_code_id, - admin: Some(env.contract.address.to_string()), - funds: vec![], - label: IMMUTABLE_WHITELIST_LABEL.to_string(), - msg: to_json_binary(&whitelist_instantiate_msg)?, - }; - Ok(SubMsg::reply_on_success(wasm_msg, INIT_WHITELIST_REPLY_ID)) - } - - pub fn state_config( - deps: Deps, - info: MessageInfo, - msg: InstantiateMsg, - ) -> Result { - Ok(Config { - admin: info.sender, - claim_msg_plaintext: msg.clone().claim_msg_plaintext, - airdrop_amount: validate_airdrop_amount(msg.airdrop_amount)?, - whitelist_address: None, - minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, - name_discount_wl_address: deps.api.addr_validate(msg.name_discount_wl_address.as_ref())?, - }) - } -} - -mod validation { - use super::*; - use cosmwasm_std::Uint128; - use cw_utils::must_pay; - use sg_std::NATIVE_DENOM; - - const MIN_AIRDROP: u128 = 10_000_000; // 10 STARS - const MAX_AIRDROP: u128 = 100_000_000_000_000; // 100 million STARS - - pub fn validate_instantiation_params( - info: MessageInfo, - msg: InstantiateMsg, - ) -> Result<(), ContractError> { - validate_airdrop_amount(msg.airdrop_amount)?; - validate_plaintext_msg(msg.claim_msg_plaintext)?; - validate_instantiate_funds(info)?; - Ok(()) - } - - pub fn validate_instantiate_funds(info: MessageInfo) -> Result<(), ContractError> { - let amount = must_pay(&info, NATIVE_DENOM)?; - if amount < Uint128::from(INSTANTIATION_FEE) { - return Err(ContractError::InsufficientFundsInstantiate {}); - }; - Ok(()) - } - - pub fn validate_airdrop_amount(airdrop_amount: u128) -> Result { - if airdrop_amount < MIN_AIRDROP { - return Err(ContractError::AirdropTooSmall {}); - }; - if airdrop_amount > MAX_AIRDROP { - return Err(ContractError::AirdropTooBig {}); - }; - Ok(airdrop_amount) - } - - pub fn validate_plaintext_msg(plaintext_msg: String) -> Result<(), ContractError> { - if !plaintext_msg.contains("{wallet}") { - return Err(ContractError::PlaintextMsgNoWallet {}); - } - if plaintext_msg.len() > 1000 { - return Err(ContractError::PlaintextTooLong {}); - } - Ok(()) - } -} diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 67e7b7a64..3eb13692e 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -43,6 +43,9 @@ pub enum ContractError { #[error("Address {address} has already claimed all available mints")] MintCountReached { address: String }, + #[error("Address {address} has already registered for the airdrop")] + AlreadyRegistered { address: String }, + #[error("Collection Whitelist on Minter contract has not been set")] CollectionWhitelistMinterNotSet {}, diff --git a/contracts/dydx-airdrop/src/lib.rs b/contracts/dydx-airdrop/src/lib.rs index 76387429a..501023d85 100644 --- a/contracts/dydx-airdrop/src/lib.rs +++ b/contracts/dydx-airdrop/src/lib.rs @@ -6,3 +6,6 @@ pub mod reply; pub mod state; pub use crate::error::ContractError; mod claim_airdrop; +mod register; +mod validation; +mod build_messages; diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index 06c49d6f5..183198b1c 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -22,6 +22,10 @@ pub struct AirdropClaimResponse { #[cw_serde] pub enum ExecuteMsg { + Register { + eth_address: String, + eth_sig: String, + }, ClaimAirdrop { eth_address: String, eth_sig: String, diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index d36a1aced..012177090 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -3,7 +3,8 @@ use cosmwasm_std::{entry_point, to_json_binary, Binary}; use cosmwasm_std::{Addr, Env}; use cosmwasm_std::{Deps, DepsMut, StdResult}; use vending_minter::helpers::MinterContract; -use whitelist_immutable::helpers::WhitelistImmutableContract; +use whitelist_immutable_flex::helpers::WhitelistImmutableFlexContract; +use whitelist_immutable_flex::msg::MemberResponse; #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { @@ -23,7 +24,7 @@ fn query_minter(deps: Deps) -> StdResult { pub fn query_airdrop_is_eligible(deps: Deps, eth_address: String) -> StdResult { let config = CONFIG.load(deps.storage)?; match config.whitelist_address { - Some(address) => WhitelistImmutableContract(deps.api.addr_validate(&address)?) + Some(address) => WhitelistImmutableFlexContract(deps.api.addr_validate(&address)?) .includes(&deps.querier, eth_address), None => Err(cosmwasm_std::StdError::NotFound { kind: "Whitelist Contract".to_string(), @@ -41,13 +42,16 @@ pub fn query_collection_whitelist(deps: &DepsMut) -> Result StdResult { +pub fn query_mint_count(deps: &DepsMut, eth_address: String) -> StdResult { let config = CONFIG.load(deps.storage)?; - match config.whitelist_address { - Some(address) => WhitelistImmutableContract(deps.api.addr_validate(&address)?) - .per_address_limit(&deps.querier), - None => Err(cosmwasm_std::StdError::NotFound { + let whitelist_address = config.whitelist_address.ok_or_else(|| { + cosmwasm_std::StdError::NotFound { kind: "Whitelist Contract".to_string(), - }), - } + } + })?; + let member_response: MemberResponse = deps.querier.query(&cosmwasm_std::QueryRequest::Wasm(cosmwasm_std::WasmQuery::Smart { + contract_addr: whitelist_address.into(), + msg: to_json_binary(&whitelist_immutable_flex::msg::QueryMsg::Member { address: eth_address })?, + }))?; + Ok(member_response.member.mint_count) } diff --git a/contracts/dydx-airdrop/src/register.rs b/contracts/dydx-airdrop/src/register.rs new file mode 100644 index 000000000..dbb58ac8f --- /dev/null +++ b/contracts/dydx-airdrop/src/register.rs @@ -0,0 +1,26 @@ +use crate::{state::CONFIG, ContractError}; +use cosmwasm_std::DepsMut; +use cosmwasm_std::{Env, MessageInfo}; +use sg_std::Response; +use crate::build_messages::{dust_and_whitelist_add}; +use crate::validation::{validate_registration}; + +pub fn register( + deps: DepsMut, + info: MessageInfo, + _env: Env, + eth_address: String, + eth_sig: String, +) -> Result { + let config = CONFIG.load(deps.storage)?; + validate_registration( + &deps, + info.clone(), + eth_address.clone(), + eth_sig, + config.clone(), + )?; + let res = dust_and_whitelist_add(&deps, info, eth_address.clone())?; + + Ok(res.add_attribute("address_registered", eth_address)) +} diff --git a/contracts/dydx-airdrop/src/state.rs b/contracts/dydx-airdrop/src/state.rs index 42f99d8b8..3eebe90e6 100644 --- a/contracts/dydx-airdrop/src/state.rs +++ b/contracts/dydx-airdrop/src/state.rs @@ -15,3 +15,4 @@ pub struct Config { pub const CONFIG: Item = Item::new("cfg"); pub const ADDRS_TO_MINT_COUNT: Map<&str, u32> = Map::new("amc"); +pub const IS_ADDRESS_REGISTERED: Map<&str, bool> = Map::new("iar"); diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index 71b433112..2e2293c0a 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -7,10 +7,57 @@ use cosmwasm_std::StdError; use ethereum_verify::verify_ethereum_text; use crate::{ - query::{query_airdrop_is_eligible, query_per_address_limit}, + query::{query_airdrop_is_eligible}, state::Config, }; +use cosmwasm_std::Uint128; +use cw_utils::must_pay; +use sg_std::NATIVE_DENOM; +use crate::contract::INSTANTIATION_FEE; +use crate::msg::InstantiateMsg; + +const MIN_AIRDROP: u128 = 10_000_000; // 10 STARS +const MAX_AIRDROP: u128 = 100_000_000_000_000; // 100 million STARS + +pub fn validate_instantiation_params( + info: MessageInfo, + msg: InstantiateMsg, +) -> Result<(), ContractError> { + validate_airdrop_amount(msg.airdrop_amount)?; + validate_plaintext_msg(msg.claim_msg_plaintext)?; + validate_instantiate_funds(info)?; + Ok(()) +} + +pub fn validate_instantiate_funds(info: MessageInfo) -> Result<(), ContractError> { + let amount = must_pay(&info, NATIVE_DENOM)?; + if amount < Uint128::from(INSTANTIATION_FEE) { + return Err(ContractError::InsufficientFundsInstantiate {}); + }; + Ok(()) +} + +pub fn validate_airdrop_amount(airdrop_amount: u128) -> Result { + if airdrop_amount < MIN_AIRDROP { + return Err(ContractError::AirdropTooSmall {}); + }; + if airdrop_amount > MAX_AIRDROP { + return Err(ContractError::AirdropTooBig {}); + }; + Ok(airdrop_amount) +} + +pub fn validate_plaintext_msg(plaintext_msg: String) -> Result<(), ContractError> { + if !plaintext_msg.contains("{wallet}") { + return Err(ContractError::PlaintextMsgNoWallet {}); + } + if plaintext_msg.len() > 1000 { + return Err(ContractError::PlaintextTooLong {}); + } + Ok(()) +} + pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { str::replace( &config.claim_msg_plaintext, @@ -41,7 +88,8 @@ pub fn validate_claim( ) -> Result<(), ContractError> { validate_is_eligible(deps, eth_address.clone())?; validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; - validate_mints_remaining(deps, ð_address)?; + // TODO: Replace with collection and names mint validation + // validate_mints_remaining(deps, ð_address)?; Ok(()) } @@ -72,20 +120,22 @@ fn validate_eth_sig( } } -pub fn validate_mints_remaining( +// TODO: Implement validate_collection_mint for reward claim +pub fn validate_collection_mint( deps: &DepsMut, eth_address: &str, ) -> Result<(), ContractError> { - let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); - let mint_count = mint_count.unwrap_or(0); - let per_address_limit = query_per_address_limit(&deps.as_ref())?; - if mint_count < per_address_limit { - Ok(()) - } else { - Err(ContractError::MintCountReached { - address: eth_address.to_string(), - }) - } + unimplemented!(); + // let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); + // let mint_count = mint_count.unwrap_or(0); + //let per_address_limit = query_per_address_limit(&deps.as_ref())?; + // if mint_count < per_address_limit { + // Ok(()) + // } else { + // Err(ContractError::MintCountReached { + // address: eth_address.to_string(), + // }) + // } } pub fn validate_ethereum_text( @@ -118,4 +168,13 @@ pub fn check_previous_registration( } else { Ok(()) } +} + +pub fn validate_required_action_completion( + deps: &DepsMut, + eth_address: &str, +) -> Result<(), ContractError> { + unimplemented!() + // validate_collection_mint() + // validate_names_mint() } \ No newline at end of file From 4362ad7abd637dc9e8494b2db4863998a28cd71b Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Tue, 12 Mar 2024 21:01:13 +0300 Subject: [PATCH 17/42] Set flag for the registered address --- contracts/dydx-airdrop/src/register.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/dydx-airdrop/src/register.rs b/contracts/dydx-airdrop/src/register.rs index dbb58ac8f..a02e84f7a 100644 --- a/contracts/dydx-airdrop/src/register.rs +++ b/contracts/dydx-airdrop/src/register.rs @@ -3,6 +3,7 @@ use cosmwasm_std::DepsMut; use cosmwasm_std::{Env, MessageInfo}; use sg_std::Response; use crate::build_messages::{dust_and_whitelist_add}; +use crate::state::IS_ADDRESS_REGISTERED; use crate::validation::{validate_registration}; pub fn register( @@ -21,6 +22,7 @@ pub fn register( config.clone(), )?; let res = dust_and_whitelist_add(&deps, info, eth_address.clone())?; + IS_ADDRESS_REGISTERED.save(deps.storage, ð_address, &true)?; Ok(res.add_attribute("address_registered", eth_address)) } From 88ad59a39de79f3c4ac3785a941c0f526bdcdaad Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Tue, 12 Mar 2024 21:05:02 +0300 Subject: [PATCH 18/42] Include name collection address among instantiation parameters --- contracts/dydx-airdrop/src/build_messages.rs | 1 + contracts/dydx-airdrop/src/msg.rs | 1 + contracts/dydx-airdrop/src/state.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/contracts/dydx-airdrop/src/build_messages.rs b/contracts/dydx-airdrop/src/build_messages.rs index 5ddf5a99d..30bed8779 100644 --- a/contracts/dydx-airdrop/src/build_messages.rs +++ b/contracts/dydx-airdrop/src/build_messages.rs @@ -44,6 +44,7 @@ pub fn state_config( whitelist_address: None, minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, name_discount_wl_address: deps.api.addr_validate(msg.name_discount_wl_address.as_ref())?, + name_collection_address: deps.api.addr_validate(msg.name_collection_address.as_ref())?, }) } diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index 183198b1c..5108d5acc 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -11,6 +11,7 @@ pub struct InstantiateMsg { pub whitelist_code_id: u64, pub minter_address: Addr, pub name_discount_wl_address: String, + pub name_collection_address: String, } #[cw_serde] diff --git a/contracts/dydx-airdrop/src/state.rs b/contracts/dydx-airdrop/src/state.rs index 3eebe90e6..e89009ef9 100644 --- a/contracts/dydx-airdrop/src/state.rs +++ b/contracts/dydx-airdrop/src/state.rs @@ -11,6 +11,7 @@ pub struct Config { pub whitelist_address: Option, pub minter_address: Addr, pub name_discount_wl_address: Addr, + pub name_collection_address: Addr, } pub const CONFIG: Item = Item::new("cfg"); From aa6f9caae55bd461f0d195ba5c6d018bc1d405bc Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 13:08:13 +0300 Subject: [PATCH 19/42] Add collection token mint validation --- Cargo.lock | 1 + contracts/dydx-airdrop/Cargo.toml | 5 +- contracts/dydx-airdrop/src/error.rs | 6 +++ contracts/dydx-airdrop/src/query.rs | 7 +++ contracts/dydx-airdrop/src/validation.rs | 65 +++++++++++------------- 5 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85e11fd33..4a0159bc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1447,6 +1447,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", + "cw721 0.18.0", "ethereum-verify", "ethers-core", "ethers-signers", diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index 7068bb8e4..eda5b0d17 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -34,7 +34,9 @@ cw2 = { workspace = true } ethereum-verify = { workspace = true } hex = "0.4" rust_decimal = { version = "1.14.3" } -sg-whitelist-flex = { workspace = true } +cw721 = { workspace = true } +sg721-base = { workspace = true } +sg-whitelist-flex = { workspace = true } sg1 = { workspace = true } sha2 = { workspace = true } sha3 = "0.10" @@ -54,7 +56,6 @@ eyre = "0.6" rlp = "0.5" sg2 = { workspace = true } vending-factory = { workspace = true } -sg721-base = { workspace = true } cw-multi-test = { workspace = true } sg-multi-test = { workspace = true } anyhow = "1.0.57" diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 3eb13692e..5190c403a 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -49,6 +49,12 @@ pub enum ContractError { #[error("Collection Whitelist on Minter contract has not been set")] CollectionWhitelistMinterNotSet {}, + #[error("Minter config is missing the collection contract address")] + CollectionContractNotSet {}, + + #[error("Need to mint a Geckies token first")] + CollectionNotMinted {}, + #[error("Plaintext message must contain `{{wallet}}` string")] PlaintextMsgNoWallet {}, diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index 012177090..121fde37a 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -42,6 +42,13 @@ pub fn query_collection_whitelist(deps: &DepsMut) -> Result StdResult { + let config = CONFIG.load(deps.storage)?; + let minter_addr = config.minter_address; + let config = MinterContract(minter_addr).config(&deps.querier)?; + Ok(config.sg721_address) +} + pub fn query_mint_count(deps: &DepsMut, eth_address: String) -> StdResult { let config = CONFIG.load(deps.storage)?; let whitelist_address = config.whitelist_address.ok_or_else(|| { diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index 2e2293c0a..19daa22cf 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -1,21 +1,21 @@ -use cosmwasm_std::{DepsMut, MessageInfo, StdResult}; -use crate::ContractError; -use crate::state::{ADDRS_TO_MINT_COUNT}; use crate::state::IS_ADDRESS_REGISTERED; +use crate::state::{ADDRS_TO_MINT_COUNT, CONFIG}; +use crate::ContractError; +use cosmwasm_std::{DepsMut, MessageInfo, StdResult}; use cosmwasm_std::StdError; use ethereum_verify::verify_ethereum_text; -use crate::{ - query::{query_airdrop_is_eligible}, - state::Config, -}; +use crate::{query::query_airdrop_is_eligible, state::Config}; +use crate::contract::INSTANTIATION_FEE; +use crate::msg::InstantiateMsg; +use crate::query::query_collection_address; use cosmwasm_std::Uint128; +use cw721::TokensResponse; use cw_utils::must_pay; +use sg721_base::msg::QueryMsg; use sg_std::NATIVE_DENOM; -use crate::contract::INSTANTIATION_FEE; -use crate::msg::InstantiateMsg; const MIN_AIRDROP: u128 = 10_000_000; // 10 STARS const MAX_AIRDROP: u128 = 100_000_000_000_000; // 100 million STARS @@ -110,8 +110,7 @@ fn validate_eth_sig( eth_sig: String, config: Config, ) -> Result<(), ContractError> { - let valid_eth_sig = - validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; + let valid_eth_sig = validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; match valid_eth_sig { true => Ok(()), false => Err(ContractError::AddressNotEligible { @@ -120,22 +119,21 @@ fn validate_eth_sig( } } -// TODO: Implement validate_collection_mint for reward claim -pub fn validate_collection_mint( - deps: &DepsMut, - eth_address: &str, -) -> Result<(), ContractError> { - unimplemented!(); - // let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); - // let mint_count = mint_count.unwrap_or(0); - //let per_address_limit = query_per_address_limit(&deps.as_ref())?; - // if mint_count < per_address_limit { - // Ok(()) - // } else { - // Err(ContractError::MintCountReached { - // address: eth_address.to_string(), - // }) - // } +pub fn validate_collection_mint(deps: &DepsMut, info: MessageInfo) -> Result<(), ContractError> { + let collection_address = query_collection_address(deps)?; + let tokens_response: TokensResponse = deps.querier.query_wasm_smart( + collection_address, + &QueryMsg::Tokens { + owner: String::from(info.sender.clone()), + start_after: None, + limit: None, + }, + )?; + return if tokens_response.tokens.len() == 0 { + Err(ContractError::CollectionNotMinted {}) + } else { + Ok(()) + }; } pub fn validate_ethereum_text( @@ -156,11 +154,10 @@ pub fn validate_ethereum_text( } } -pub fn check_previous_registration( - deps: &DepsMut, - eth_address: &str, -) -> Result<(), ContractError> { - let registered = IS_ADDRESS_REGISTERED.load(deps.storage, eth_address).unwrap_or(false); +pub fn check_previous_registration(deps: &DepsMut, eth_address: &str) -> Result<(), ContractError> { + let registered = IS_ADDRESS_REGISTERED + .load(deps.storage, eth_address) + .unwrap_or(false); if registered { Err(ContractError::AlreadyRegistered { address: eth_address.to_string(), @@ -174,7 +171,7 @@ pub fn validate_required_action_completion( deps: &DepsMut, eth_address: &str, ) -> Result<(), ContractError> { - unimplemented!() + unimplemented!() // validate_collection_mint() // validate_names_mint() -} \ No newline at end of file +} From 868ae499ff838c227c9cf2e51d7dcebe40bd4b7e Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 14:37:24 +0300 Subject: [PATCH 20/42] Add validation for name mint & association --- Cargo.lock | 148 +++++++++++++++++++---- Cargo.toml | 1 + contracts/dydx-airdrop/Cargo.toml | 5 +- contracts/dydx-airdrop/src/error.rs | 3 + contracts/dydx-airdrop/src/validation.rs | 24 ++++ 5 files changed, 155 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a0159bc5..3c0d44c8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,8 +373,8 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", "thiserror", "url", ] @@ -1462,7 +1462,8 @@ dependencies = [ "sg-whitelist-flex", "sg1", "sg2", - "sg721-base", + "sg721-base 3.5.0", + "sg721-name", "sha2 0.10.8", "sha3", "thiserror", @@ -1495,8 +1496,8 @@ dependencies = [ "serde_json", "sg-metadata", "sg2", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", "test-context", "vending-factory", "vending-minter", @@ -2674,7 +2675,7 @@ dependencies = [ "sg-std 3.2.0", "sg1", "sg2", - "sg721", + "sg721 3.5.0", "thiserror", ] @@ -2696,7 +2697,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "thiserror", "url", ] @@ -3254,7 +3255,7 @@ dependencies = [ "sg-whitelist", "sg1", "sg2", - "sg721-base", + "sg721-base 3.5.0", "sha2 0.10.8", "sha3", "thiserror", @@ -3793,6 +3794,30 @@ dependencies = [ "sg-std 3.2.0", ] +[[package]] +name = "sg-name" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba179e312060ca767f809353a3181a9f7a94932f2498d9b0f337229063a6b93" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "sg-name-market" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c1d3bc0742d8ad86ce05aaeb15835954f665e21da96dc18c7c7412eaa3befa" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "sg-name-minter" version = "0.12.0" @@ -3839,6 +3864,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sg-std" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd076abea035a2da34a770eb7a239a4fbffa59d3a193ab91e07fb81583937c5c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "cw721 0.16.0", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "sg-std" version = "3.2.0" @@ -3921,7 +3961,7 @@ dependencies = [ "cw-utils 1.0.3", "schemars", "serde", - "sg721", + "sg721 3.5.0", "thiserror", ] @@ -3936,6 +3976,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sg721" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a8c0cb5748e59d506cb7cf375d1f03769f1e3586a1542be8a199730721c6102" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "cw721-base 0.16.0", + "serde", + "thiserror", +] + [[package]] name = "sg721" version = "3.5.0" @@ -3950,6 +4004,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sg721-base" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6c3ba2af031105758e21f94e8a1488bf810b33914b7e49d7ef5efcf1936cf96" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw721 0.16.0", + "cw721-base 0.16.0", + "serde", + "sg-std 0.22.11", + "sg721 0.22.11", + "thiserror", + "url", +] + [[package]] name = "sg721-base" version = "3.5.0" @@ -3964,7 +4038,7 @@ dependencies = [ "cw721-base 0.18.0", "serde", "sg-std 3.2.0", - "sg721", + "sg721 3.5.0", "thiserror", "url", ] @@ -3983,8 +4057,34 @@ dependencies = [ "serde", "sg-metadata", "sg-std 3.2.0", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", +] + +[[package]] +name = "sg721-name" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc40d7bb875a788848daacac5d8d3e894f48f8c282a3d704f3492ffa9261ede" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.16.0", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw721 0.16.0", + "cw721-base 0.16.0", + "schemars", + "semver", + "serde", + "sg-name", + "sg-name-market", + "sg-std 0.22.11", + "sg721 0.22.11", + "sg721-base 0.22.11", + "subtle-encoding", + "thiserror", ] [[package]] @@ -4000,8 +4100,8 @@ dependencies = [ "schemars", "serde", "sg-std 3.2.0", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", ] [[package]] @@ -4021,8 +4121,8 @@ dependencies = [ "serde", "sg-std 3.2.0", "sg1", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", "thiserror", ] @@ -4430,8 +4530,8 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", - "sg721-base", + "sg721 3.5.0", + "sg721-base 3.5.0", "sg721-nt", "sg721-updatable", "sha2 0.10.8", @@ -4854,7 +4954,7 @@ dependencies = [ "sg-std 3.2.0", "sg1", "sg2", - "sg721", + "sg721 3.5.0", "thiserror", ] @@ -4879,7 +4979,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "sha2 0.10.8", "shuffle", "thiserror", @@ -4908,7 +5008,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "sha2 0.10.8", "shuffle", "thiserror", @@ -4937,7 +5037,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "sha2 0.10.8", "shuffle", "thiserror", @@ -4967,7 +5067,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "sha2 0.10.8", "shuffle", "thiserror", @@ -4996,7 +5096,7 @@ dependencies = [ "sg1", "sg2", "sg4", - "sg721", + "sg721 3.5.0", "sha2 0.10.8", "shuffle", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 6526185ed..b43e38405 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whiteli whitelist-immutable-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable-flex" } whitelist-updatable = "0.12.0" sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } +sg721-name = "1.2.5" ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } rekt-airdrop = { version = "3.5.0", path = "contracts/rekt-airdrop"} dydx-airdrop = { version = "3.5.0", path = "contracts/dydx-airdrop"} diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index eda5b0d17..55e52e8dd 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -35,8 +35,9 @@ ethereum-verify = { workspace = true } hex = "0.4" rust_decimal = { version = "1.14.3" } cw721 = { workspace = true } -sg721-base = { workspace = true } -sg-whitelist-flex = { workspace = true } +sg721-base = { workspace = true, features = ["library"] } +sg721-name = { workspace = true, features = ["library"] } +sg-whitelist-flex = { workspace = true, features = ["library"] } sg1 = { workspace = true } sha2 = { workspace = true } sha3 = "0.10" diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 5190c403a..6ea6ff5f5 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -55,6 +55,9 @@ pub enum ContractError { #[error("Need to mint a Geckies token first")] CollectionNotMinted {}, + #[error("Need to mint a name first")] + NameNotMinted {}, + #[error("Plaintext message must contain `{{wallet}}` string")] PlaintextMsgNoWallet {}, diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index 19daa22cf..d3d152111 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -15,6 +15,7 @@ use cosmwasm_std::Uint128; use cw721::TokensResponse; use cw_utils::must_pay; use sg721_base::msg::QueryMsg; +use sg721_name::msg::QueryMsg as NameQueryMsg; use sg_std::NATIVE_DENOM; const MIN_AIRDROP: u128 = 10_000_000; // 10 STARS @@ -136,6 +137,29 @@ pub fn validate_collection_mint(deps: &DepsMut, info: MessageInfo) -> Result<(), }; } +pub fn validate_name_mint_and_association(deps: &DepsMut, info: MessageInfo) -> Result<(), ContractError> { + let config = CONFIG.load(deps.storage)?; + let name_collection_address = config.name_collection_address; + let tokens_response: TokensResponse = deps.querier.query_wasm_smart( + name_collection_address.clone(), + &QueryMsg::Tokens { + owner: String::from(info.sender.clone()), + start_after: None, + limit: None, + }, + )?; + if tokens_response.tokens.len() == 0 { + return Err(ContractError::NameNotMinted {}) + }; + let associated_name: String = deps.querier.query_wasm_smart( + name_collection_address.clone(), + &NameQueryMsg::Name { + address: String::from(info.sender.clone()), + }, + )?; + Ok(()) +} + pub fn validate_ethereum_text( deps: &DepsMut, info: MessageInfo, From 7ffa28422b4e3d0d0db0878e3ff825a22cdb42b6 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 15:31:59 +0300 Subject: [PATCH 21/42] Check for previous claims --- contracts/dydx-airdrop/src/error.rs | 3 ++ contracts/dydx-airdrop/src/state.rs | 1 + contracts/dydx-airdrop/src/validation.rs | 36 +++++++++++++----------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 6ea6ff5f5..5f4bc8a5c 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -46,6 +46,9 @@ pub enum ContractError { #[error("Address {address} has already registered for the airdrop")] AlreadyRegistered { address: String }, + #[error("Address {address} has already claimed the airdrop")] + AlreadyClaimed { address: String }, + #[error("Collection Whitelist on Minter contract has not been set")] CollectionWhitelistMinterNotSet {}, diff --git a/contracts/dydx-airdrop/src/state.rs b/contracts/dydx-airdrop/src/state.rs index e89009ef9..5946a5e36 100644 --- a/contracts/dydx-airdrop/src/state.rs +++ b/contracts/dydx-airdrop/src/state.rs @@ -17,3 +17,4 @@ pub struct Config { pub const CONFIG: Item = Item::new("cfg"); pub const ADDRS_TO_MINT_COUNT: Map<&str, u32> = Map::new("amc"); pub const IS_ADDRESS_REGISTERED: Map<&str, bool> = Map::new("iar"); +pub const HAS_CLAIMED: Map<&str, bool> = Map::new("hc"); diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index d3d152111..e275750b4 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -1,5 +1,5 @@ -use crate::state::IS_ADDRESS_REGISTERED; use crate::state::{ADDRS_TO_MINT_COUNT, CONFIG}; +use crate::state::{HAS_CLAIMED, IS_ADDRESS_REGISTERED}; use crate::ContractError; use cosmwasm_std::{DepsMut, MessageInfo, StdResult}; @@ -88,9 +88,10 @@ pub fn validate_claim( config: Config, ) -> Result<(), ContractError> { validate_is_eligible(deps, eth_address.clone())?; - validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; - // TODO: Replace with collection and names mint validation - // validate_mints_remaining(deps, ð_address)?; + validate_eth_sig(deps, info.clone(), eth_address.clone(), eth_sig, config)?; + check_previous_claim(deps, ð_address.clone())?; + validate_collection_mint(deps, info.clone())?; + validate_name_mint_and_association(deps, info.clone())?; Ok(()) } @@ -137,7 +138,10 @@ pub fn validate_collection_mint(deps: &DepsMut, info: MessageInfo) -> Result<(), }; } -pub fn validate_name_mint_and_association(deps: &DepsMut, info: MessageInfo) -> Result<(), ContractError> { +pub fn validate_name_mint_and_association( + deps: &DepsMut, + info: MessageInfo, +) -> Result<(), ContractError> { let config = CONFIG.load(deps.storage)?; let name_collection_address = config.name_collection_address; let tokens_response: TokensResponse = deps.querier.query_wasm_smart( @@ -149,7 +153,7 @@ pub fn validate_name_mint_and_association(deps: &DepsMut, info: MessageInfo) -> }, )?; if tokens_response.tokens.len() == 0 { - return Err(ContractError::NameNotMinted {}) + return Err(ContractError::NameNotMinted {}); }; let associated_name: String = deps.querier.query_wasm_smart( name_collection_address.clone(), @@ -183,19 +187,19 @@ pub fn check_previous_registration(deps: &DepsMut, eth_address: &str) -> Result< .load(deps.storage, eth_address) .unwrap_or(false); if registered { - Err(ContractError::AlreadyRegistered { + return Err(ContractError::AlreadyRegistered { address: eth_address.to_string(), }) - } else { - Ok(()) } + Ok(()) } -pub fn validate_required_action_completion( - deps: &DepsMut, - eth_address: &str, -) -> Result<(), ContractError> { - unimplemented!() - // validate_collection_mint() - // validate_names_mint() +pub fn check_previous_claim(deps: &DepsMut, eth_address: &str) -> Result<(), ContractError> { + let already_claimed = HAS_CLAIMED.load(deps.storage, eth_address).unwrap_or(false); + if already_claimed { + return Err(ContractError::AlreadyClaimed { + address: eth_address.to_string(), + }) + } + Ok(()) } From 48aacbd544b2e42640393e6ab7d2d1b3e516098d Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 15:32:51 +0300 Subject: [PATCH 22/42] Add claim_airdrop() --- contracts/dydx-airdrop/src/claim_airdrop.rs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/contracts/dydx-airdrop/src/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs index 131235265..78c430206 100644 --- a/contracts/dydx-airdrop/src/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -1,4 +1,4 @@ -use crate::state::ADDRS_TO_MINT_COUNT; +use crate::state::{ADDRS_TO_MINT_COUNT, HAS_CLAIMED}; use crate::{state::CONFIG, ContractError}; use cosmwasm_std::DepsMut; use cosmwasm_std::{Env, MessageInfo}; @@ -23,21 +23,6 @@ pub fn claim_airdrop( config.clone(), )?; let res = claim_reward(info, config.airdrop_amount)?; - - // TODO: To be removed - increment_local_mint_count_for_address(deps, eth_address)?; - + HAS_CLAIMED.save(deps.storage, ð_address, &true)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) } - -pub fn increment_local_mint_count_for_address( - deps: DepsMut, - eth_address: String, -) -> Result { - let mint_count_for_address = ADDRS_TO_MINT_COUNT - .load(deps.storage, ð_address) - .unwrap_or(0); - ADDRS_TO_MINT_COUNT.save(deps.storage, ð_address, &(mint_count_for_address + 1))?; - - Ok(Response::new()) -} From fff2a30d989aa2a2b432eac29ab98e3f1dbad71e Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 16:33:42 +0300 Subject: [PATCH 23/42] Check for total airdrop count for reward distribution --- contracts/dydx-airdrop/src/build_messages.rs | 50 ++++++++++--------- contracts/dydx-airdrop/src/claim_airdrop.rs | 11 +++- contracts/dydx-airdrop/src/contract.rs | 3 +- contracts/dydx-airdrop/src/error.rs | 3 ++ contracts/dydx-airdrop/src/lib.rs | 2 +- contracts/dydx-airdrop/src/msg.rs | 1 + contracts/dydx-airdrop/src/query.rs | 23 +++++---- contracts/dydx-airdrop/src/register.rs | 6 +-- contracts/dydx-airdrop/src/state.rs | 2 + contracts/dydx-airdrop/src/validation.rs | 8 +-- test-suite/src/common_setup/contract_boxes.rs | 2 +- .../src/dydx_airdrop/tests/test_claim.rs | 5 +- .../tests/test_collection_whitelist.rs | 4 +- .../tests/test_immutable_whitelist.rs | 5 +- 14 files changed, 77 insertions(+), 48 deletions(-) diff --git a/contracts/dydx-airdrop/src/build_messages.rs b/contracts/dydx-airdrop/src/build_messages.rs index 30bed8779..a7712ddff 100644 --- a/contracts/dydx-airdrop/src/build_messages.rs +++ b/contracts/dydx-airdrop/src/build_messages.rs @@ -1,16 +1,18 @@ -use cosmwasm_std::{Addr, BankMsg, coins, Deps, DepsMut, Env, MessageInfo, StdResult, to_json_binary, WasmMsg}; -use sg_std::{CosmosMsg, NATIVE_DENOM, Response, StargazeMsgWrapper, SubMsg}; +use cosmwasm_std::{ + coins, to_json_binary, Addr, BankMsg, Deps, DepsMut, Env, MessageInfo, StdResult, WasmMsg, +}; +use sg_std::{CosmosMsg, Response, StargazeMsgWrapper, SubMsg, NATIVE_DENOM}; use whitelist_updatable::msg::ExecuteMsg; // TODO: Replace with whitelist_updatable_flatrate -use whitelist_updatable::msg::ExecuteMsg::AddAddresses; -use sg_whitelist_flex::helpers::interface::CollectionWhitelistContract; -use crate::ContractError; +use crate::msg::InstantiateMsg; use crate::query::{query_collection_whitelist, query_mint_count}; -use sg_whitelist_flex::msg::{ExecuteMsg as CollectionWhitelistExecuteMsg, Member}; +use crate::state::{Config, CONFIG}; +use crate::ContractError; +use sg_whitelist_flex::helpers::interface::CollectionWhitelistContract; use sg_whitelist_flex::msg::AddMembersMsg; -use crate::msg::InstantiateMsg; -use crate::state::{CONFIG, Config}; +use sg_whitelist_flex::msg::{ExecuteMsg as CollectionWhitelistExecuteMsg, Member}; use whitelist_immutable_flex::msg::InstantiateMsg as WIFInstantiateMsg; +use whitelist_updatable::msg::ExecuteMsg::AddAddresses; pub const IMMUTABLE_WHITELIST_LABEL: &str = "Whitelist Immutable Flex for Airdrop"; pub const INIT_WHITELIST_REPLY_ID: u64 = 1; @@ -43,16 +45,17 @@ pub fn state_config( airdrop_amount: crate::validation::validate_airdrop_amount(msg.airdrop_amount)?, whitelist_address: None, minter_address: deps.api.addr_validate(msg.minter_address.as_ref())?, - name_discount_wl_address: deps.api.addr_validate(msg.name_discount_wl_address.as_ref())?, - name_collection_address: deps.api.addr_validate(msg.name_collection_address.as_ref())?, + name_discount_wl_address: deps + .api + .addr_validate(msg.name_discount_wl_address.as_ref())?, + name_collection_address: deps + .api + .addr_validate(msg.name_collection_address.as_ref())?, + airdrop_count_limit: msg.airdrop_count_limit, }) } -pub fn claim_reward( - info: MessageInfo, - airdrop_amount: u128, -) -> Result { - // TODO: add a limit to the number of claims (500 as per the proposal) +pub fn claim_reward(info: MessageInfo, airdrop_amount: u128) -> Result { let mut res = Response::new(); let bank_msg = SubMsg::new(BankMsg::Send { to_address: info.sender.to_string(), @@ -80,7 +83,7 @@ pub fn add_member_to_whitelists( let config = CONFIG.load(deps.storage)?; let collection_whitelist = query_collection_whitelist(deps)?; let mint_count = query_mint_count(deps, eth_address.clone())?; - let names_discount_whitelist = config.name_discount_wl_address; + let names_discount_whitelist = config.name_discount_wl_address; let res = Response::new(); let res = res.add_message(add_member_to_collection_whitelist( @@ -109,30 +112,29 @@ fn add_member_to_collection_whitelist( }], }; let execute_msg = CollectionWhitelistExecuteMsg::AddMembers(inner_msg); - CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?) - .call(execute_msg) + CollectionWhitelistContract(deps.api.addr_validate(&collection_whitelist)?).call(execute_msg) } fn add_member_to_names_discount_whitelist( wallet_address: Addr, name_discount_wl: String, ) -> StdResult { - let execute_msg: ExecuteMsg = AddAddresses { addresses: vec![wallet_address.to_string()] }; + let execute_msg: ExecuteMsg = AddAddresses { + addresses: vec![wallet_address.to_string()], + }; let msg = to_json_binary(&execute_msg)?; Ok(WasmMsg::Execute { contract_addr: name_discount_wl, msg, funds: vec![], } - .into()) + .into()) } -pub fn dust_member_wallet( - info: MessageInfo, -) -> StdResult { +pub fn dust_member_wallet(info: MessageInfo) -> StdResult { let inner_msg = BankMsg::Send { to_address: info.sender.to_string(), amount: coins(1000000, NATIVE_DENOM), }; Ok(CosmosMsg::Bank(inner_msg)) -} \ No newline at end of file +} diff --git a/contracts/dydx-airdrop/src/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs index 78c430206..b78d86bc5 100644 --- a/contracts/dydx-airdrop/src/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -1,9 +1,9 @@ -use crate::state::{ADDRS_TO_MINT_COUNT, HAS_CLAIMED}; +use crate::build_messages::claim_reward; +use crate::state::{AIRDROP_COUNT, HAS_CLAIMED}; use crate::{state::CONFIG, ContractError}; use cosmwasm_std::DepsMut; use cosmwasm_std::{Env, MessageInfo}; use sg_std::Response; -use crate::build_messages::{claim_reward}; use crate::validation::validate_claim; @@ -15,6 +15,10 @@ pub fn claim_airdrop( eth_sig: String, ) -> Result { let config = CONFIG.load(deps.storage)?; + let airdrop_count_limit = config.airdrop_count_limit; + if AIRDROP_COUNT.load(deps.storage)? >= airdrop_count_limit { + return Err(ContractError::AirdropCountLimitExceeded {}); + } validate_claim( &deps, info.clone(), @@ -23,6 +27,9 @@ pub fn claim_airdrop( config.clone(), )?; let res = claim_reward(info, config.airdrop_amount)?; + AIRDROP_COUNT.update(deps.storage, |count: u32| -> Result { + Ok(count + 1) + })?; HAS_CLAIMED.save(deps.storage, ð_address, &true)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) } diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index 5c4f673e4..2fa7d4d95 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -2,7 +2,7 @@ use crate::claim_airdrop::claim_airdrop; #[cfg(not(feature = "library"))] use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg}; -use crate::state::CONFIG; +use crate::state::{AIRDROP_COUNT, CONFIG}; use cosmwasm_std::entry_point; use cosmwasm_std::{DepsMut, Env, MessageInfo}; @@ -29,6 +29,7 @@ pub fn instantiate( validate_instantiation_params(info.clone(), msg.clone())?; let mut res = Response::new(); fair_burn(INSTANTIATION_FEE, None, &mut res); + AIRDROP_COUNT.save(deps.storage, &0)?; let cfg = state_config(deps.as_ref(), info.clone(), msg.clone())?; CONFIG.save(deps.storage, &cfg)?; Ok(res diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 5f4bc8a5c..1f091c3d9 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -61,6 +61,9 @@ pub enum ContractError { #[error("Need to mint a name first")] NameNotMinted {}, + #[error("Airdrop count limit exceeded")] + AirdropCountLimitExceeded {}, + #[error("Plaintext message must contain `{{wallet}}` string")] PlaintextMsgNoWallet {}, diff --git a/contracts/dydx-airdrop/src/lib.rs b/contracts/dydx-airdrop/src/lib.rs index 501023d85..1ecfe337a 100644 --- a/contracts/dydx-airdrop/src/lib.rs +++ b/contracts/dydx-airdrop/src/lib.rs @@ -5,7 +5,7 @@ pub mod query; pub mod reply; pub mod state; pub use crate::error::ContractError; +mod build_messages; mod claim_airdrop; mod register; mod validation; -mod build_messages; diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index 5108d5acc..a13549bf2 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -12,6 +12,7 @@ pub struct InstantiateMsg { pub minter_address: Addr, pub name_discount_wl_address: String, pub name_collection_address: String, + pub airdrop_count_limit: u32, } #[cw_serde] diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index 121fde37a..25e4bec57 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -51,14 +51,19 @@ pub fn query_collection_address(deps: &DepsMut) -> StdResult { pub fn query_mint_count(deps: &DepsMut, eth_address: String) -> StdResult { let config = CONFIG.load(deps.storage)?; - let whitelist_address = config.whitelist_address.ok_or_else(|| { - cosmwasm_std::StdError::NotFound { - kind: "Whitelist Contract".to_string(), - } - })?; - let member_response: MemberResponse = deps.querier.query(&cosmwasm_std::QueryRequest::Wasm(cosmwasm_std::WasmQuery::Smart { - contract_addr: whitelist_address.into(), - msg: to_json_binary(&whitelist_immutable_flex::msg::QueryMsg::Member { address: eth_address })?, - }))?; + let whitelist_address = + config + .whitelist_address + .ok_or_else(|| cosmwasm_std::StdError::NotFound { + kind: "Whitelist Contract".to_string(), + })?; + let member_response: MemberResponse = deps.querier.query(&cosmwasm_std::QueryRequest::Wasm( + cosmwasm_std::WasmQuery::Smart { + contract_addr: whitelist_address.into(), + msg: to_json_binary(&whitelist_immutable_flex::msg::QueryMsg::Member { + address: eth_address, + })?, + }, + ))?; Ok(member_response.member.mint_count) } diff --git a/contracts/dydx-airdrop/src/register.rs b/contracts/dydx-airdrop/src/register.rs index a02e84f7a..7a8c1ad38 100644 --- a/contracts/dydx-airdrop/src/register.rs +++ b/contracts/dydx-airdrop/src/register.rs @@ -1,10 +1,10 @@ +use crate::build_messages::dust_and_whitelist_add; +use crate::state::IS_ADDRESS_REGISTERED; +use crate::validation::validate_registration; use crate::{state::CONFIG, ContractError}; use cosmwasm_std::DepsMut; use cosmwasm_std::{Env, MessageInfo}; use sg_std::Response; -use crate::build_messages::{dust_and_whitelist_add}; -use crate::state::IS_ADDRESS_REGISTERED; -use crate::validation::{validate_registration}; pub fn register( deps: DepsMut, diff --git a/contracts/dydx-airdrop/src/state.rs b/contracts/dydx-airdrop/src/state.rs index 5946a5e36..0effe836d 100644 --- a/contracts/dydx-airdrop/src/state.rs +++ b/contracts/dydx-airdrop/src/state.rs @@ -12,9 +12,11 @@ pub struct Config { pub minter_address: Addr, pub name_discount_wl_address: Addr, pub name_collection_address: Addr, + pub airdrop_count_limit: u32, } pub const CONFIG: Item = Item::new("cfg"); pub const ADDRS_TO_MINT_COUNT: Map<&str, u32> = Map::new("amc"); pub const IS_ADDRESS_REGISTERED: Map<&str, bool> = Map::new("iar"); pub const HAS_CLAIMED: Map<&str, bool> = Map::new("hc"); +pub const AIRDROP_COUNT: Item = Item::new("ac"); diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index e275750b4..2030e707d 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -1,4 +1,4 @@ -use crate::state::{ADDRS_TO_MINT_COUNT, CONFIG}; +use crate::state::CONFIG; use crate::state::{HAS_CLAIMED, IS_ADDRESS_REGISTERED}; use crate::ContractError; use cosmwasm_std::{DepsMut, MessageInfo, StdResult}; @@ -155,7 +155,7 @@ pub fn validate_name_mint_and_association( if tokens_response.tokens.len() == 0 { return Err(ContractError::NameNotMinted {}); }; - let associated_name: String = deps.querier.query_wasm_smart( + let _associated_name: String = deps.querier.query_wasm_smart( name_collection_address.clone(), &NameQueryMsg::Name { address: String::from(info.sender.clone()), @@ -189,7 +189,7 @@ pub fn check_previous_registration(deps: &DepsMut, eth_address: &str) -> Result< if registered { return Err(ContractError::AlreadyRegistered { address: eth_address.to_string(), - }) + }); } Ok(()) } @@ -199,7 +199,7 @@ pub fn check_previous_claim(deps: &DepsMut, eth_address: &str) -> Result<(), Con if already_claimed { return Err(ContractError::AlreadyClaimed { address: eth_address.to_string(), - }) + }); } Ok(()) } diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 6caee0bc7..6b9684f1c 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -137,7 +137,7 @@ pub fn contract_dydx_airdrop() -> Box> { dydx_airdrop::contract::instantiate, dydx_airdrop::query::query, ) - .with_reply(dydx_airdrop::reply::reply); + .with_reply(dydx_airdrop::reply::reply); Box::new(contract) } diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index a08a0dd6c..ca92245e3 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -13,7 +13,10 @@ use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, + NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, +}; use crate::dydx_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, diff --git a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index 07e9f9658..bb3270b2d 100644 --- a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,6 +1,8 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01, +}; use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; diff --git a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index d37346c90..428ac7731 100644 --- a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -1,5 +1,8 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, + OWNER, +}; use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; From f04812104477c9d13c443d709add92cb3d8eedef Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 13 Mar 2024 16:36:49 +0300 Subject: [PATCH 24/42] Address clippy issues --- contracts/whitelists/whitelist-immutable-flex/src/helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs index 7074b86d0..2fef1db7a 100644 --- a/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs +++ b/contracts/whitelists/whitelist-immutable-flex/src/helpers.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{to_json_binary, Addr, QuerierWrapper, QueryRequest, StdResult, WasmQuery}; -use crate::msg::{Member, MemberResponse}; +use crate::msg::MemberResponse; use crate::{ msg::{ConfigResponse, QueryMsg}, state::Config, From d1df392c1e7860756577c3245a6754ba1834ada9 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Thu, 14 Mar 2024 17:27:59 +0300 Subject: [PATCH 25/42] Update test-suite/common_setup to include whitelist-flex --- Cargo.lock | 3 + test-suite/Cargo.toml | 5 +- test-suite/src/common_setup.rs | 1 + test-suite/src/common_setup/contract_boxes.rs | 9 ++ .../setup_collection_whitelist_flex.rs | 116 ++++++++++++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 test-suite/src/common_setup/setup_collection_whitelist_flex.rs diff --git a/Cargo.lock b/Cargo.lock index 3c0d44c8c..272a7c0ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4527,11 +4527,13 @@ dependencies = [ "sg-splits", "sg-std 3.2.0", "sg-whitelist", + "sg-whitelist-flex", "sg1", "sg2", "sg4", "sg721 3.5.0", "sg721-base 3.5.0", + "sg721-name", "sg721-nt", "sg721-updatable", "sha2 0.10.8", @@ -4544,6 +4546,7 @@ dependencies = [ "whitelist-immutable", "whitelist-immutable-flex", "whitelist-mtree", + "whitelist-updatable", ] [[package]] diff --git a/test-suite/Cargo.toml b/test-suite/Cargo.toml index 99024d936..629f2bec5 100644 --- a/test-suite/Cargo.toml +++ b/test-suite/Cargo.toml @@ -48,6 +48,8 @@ rekt-airdrop = { workspace = true } dydx-airdrop = { workspace = true } whitelist-immutable = { workspace = true, features = ["library"] } whitelist-immutable-flex = { workspace = true, features = ["library"] } +whitelist-updatable = { workspace = true, features = ["library"] } +sg721-name = { workspace = true } cw721 = { workspace = true } cw721-base = { workspace = true, features = ["library"] } sg2 = { workspace = true } @@ -55,7 +57,8 @@ sg721 = { workspace = true } sg-metadata = { workspace = true } open-edition-factory = { workspace = true, features = ["library"] } open-edition-minter = { workspace = true, features = ["library"] } -sg-whitelist = { workspace = true, features = ["library"] } +sg-whitelist = { workspace = true, features = ["library"] } +sg-whitelist-flex = { workspace = true, features = ["library"] } vending-factory = { workspace = true, features = ["library"] } vending-minter = { workspace = true, features = ["library"] } base-factory = { workspace = true } diff --git a/test-suite/src/common_setup.rs b/test-suite/src/common_setup.rs index cc10d8105..278072a80 100644 --- a/test-suite/src/common_setup.rs +++ b/test-suite/src/common_setup.rs @@ -4,6 +4,7 @@ pub mod helpers; pub mod msg; pub mod setup_accounts_and_block; pub mod setup_collection_whitelist; +pub mod setup_collection_whitelist_flex; pub mod setup_minter; pub mod setup_whitelist_merkletree; pub mod templates; diff --git a/test-suite/src/common_setup/contract_boxes.rs b/test-suite/src/common_setup/contract_boxes.rs index 6b9684f1c..f21b7a0e0 100644 --- a/test-suite/src/common_setup/contract_boxes.rs +++ b/test-suite/src/common_setup/contract_boxes.rs @@ -64,6 +64,15 @@ pub fn contract_collection_whitelist() -> Box> Box::new(contract) } +pub fn contract_collection_whitelist_flex() -> Box> { + let contract = ContractWrapper::new( + sg_whitelist_flex::contract::execute, + sg_whitelist_flex::contract::instantiate, + sg_whitelist_flex::contract::query, + ); + Box::new(contract) +} + pub fn contract_open_edition_minter() -> Box> { let contract = ContractWrapper::new( open_edition_minter::contract::execute, diff --git a/test-suite/src/common_setup/setup_collection_whitelist_flex.rs b/test-suite/src/common_setup/setup_collection_whitelist_flex.rs new file mode 100644 index 000000000..abe182c7b --- /dev/null +++ b/test-suite/src/common_setup/setup_collection_whitelist_flex.rs @@ -0,0 +1,116 @@ +use cosmwasm_std::{coin, Addr, Timestamp}; +use cw_multi_test::Executor; +use sg_multi_test::StargazeApp; +use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; +use sg_whitelist_flex::msg::InstantiateMsg as WhitelistFlexInstantiateMsg; + +use crate::common_setup::{ + contract_boxes::contract_collection_whitelist_flex, setup_accounts_and_block::setup_block_time, +}; + +pub const WHITELIST_AMOUNT: u128 = 66_000_000; +const ZERO_FEE_WHITELIST: u128 = 0; +pub fn setup_whitelist_flex_contract( + router: &mut StargazeApp, + creator: &Addr, + whitelist_code_id: Option, + denom: Option<&str>, +) -> Addr { + let whitelist_code_id = match whitelist_code_id { + Some(value) => value, + None => router.store_code(contract_collection_whitelist_flex()), + }; + let denom = match denom { + Some(value) => value, + None => NATIVE_DENOM, + }; + + let msg = WhitelistFlexInstantiateMsg { + members: vec![], + start_time: Timestamp::from_nanos(GENESIS_MINT_START_TIME + 100), + end_time: Timestamp::from_nanos(GENESIS_MINT_START_TIME + 10000000), + mint_price: coin(WHITELIST_AMOUNT, denom), + member_limit: 1000, + admins: vec![creator.to_string()], + admins_mutable: true, + whale_cap: None, + }; + router + .instantiate_contract( + whitelist_code_id, + creator.clone(), + &msg, + &[coin(100_000_000, NATIVE_DENOM)], + "whitelist", + None, + ) + .unwrap() +} + +pub fn setup_zero_fee_whitelist_contract( + router: &mut StargazeApp, + creator: &Addr, + whitelist_code_id: Option, +) -> Addr { + let whitelist_code_id = match whitelist_code_id { + Some(value) => value, + None => router.store_code(contract_collection_whitelist_flex()), + }; + + let msg = WhitelistFlexInstantiateMsg { + members: vec![], + start_time: Timestamp::from_nanos(GENESIS_MINT_START_TIME + 100), + end_time: Timestamp::from_nanos(GENESIS_MINT_START_TIME + 10000000), + mint_price: coin(ZERO_FEE_WHITELIST, NATIVE_DENOM), + member_limit: 1000, + admins: vec![creator.to_string()], + admins_mutable: true, + whale_cap: None, + }; + router + .instantiate_contract( + whitelist_code_id, + creator.clone(), + &msg, + &[coin(100_000_000, NATIVE_DENOM)], + "whitelist", + None, + ) + .unwrap() +} + +pub fn configure_collection_whitelist_flex( + router: &mut StargazeApp, + creator: Addr, + buyer: Addr, + minter_addr: Addr, +) -> Addr { + let whitelist_flex_addr = setup_whitelist_flex_contract(router, &creator, None, None); + const AFTER_GENESIS_TIME: Timestamp = Timestamp::from_nanos(GENESIS_MINT_START_TIME + 100); + + // Set to just before genesis mint start time + setup_block_time(router, GENESIS_MINT_START_TIME - 10, None); + + // Update whitelist_expiration fails if not admin + let wl_msg = sg_whitelist_flex::msg::ExecuteMsg::UpdateEndTime(AFTER_GENESIS_TIME); + router + .execute_contract(buyer, whitelist_addr.clone(), &wl_msg, &[]) + .unwrap_err(); + + // Update whitelist_expiration succeeds when from admin + let wl_msg = sg_whitelist_flex::msg::ExecuteMsg::UpdateEndTime(AFTER_GENESIS_TIME); + let res = router.execute_contract(creator.clone(), whitelist_flex_addr.clone(), &wl_msg, &[]); + assert!(res.is_ok()); + + let wl_msg = sg_whitelist_flex::msg::ExecuteMsg::UpdateStartTime(Timestamp::from_nanos(0)); + let res = router.execute_contract(creator.clone(), whitelist_flex_addr.clone(), &wl_msg, &[]); + assert!(res.is_ok()); + + // Set whitelist in minter contract + let set_whitelist_msg = vending_minter::msg::ExecuteMsg::SetWhitelist { + whitelist: whitelist_flex_addr.to_string(), + }; + let res = router.execute_contract(creator, minter_addr, &set_whitelist_msg, &[]); + assert!(res.is_ok()); + whitelist_flex_addr +} From 868355baaba41a7301102e2edb4d2ce63330eb00 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Fri, 15 Mar 2024 15:14:44 +0300 Subject: [PATCH 26/42] Add TS interface & types --- .../dydx-airdrop/schema/dydx-airdrop.json | 81 ++++++++++--- ts/src/DydxAirdrop.client.ts | 107 ++++++++++++++++++ ts/src/DydxAirdrop.types.ts | 41 +++++++ 3 files changed, 212 insertions(+), 17 deletions(-) create mode 100644 ts/src/DydxAirdrop.client.ts create mode 100644 ts/src/DydxAirdrop.types.ts diff --git a/contracts/dydx-airdrop/schema/dydx-airdrop.json b/contracts/dydx-airdrop/schema/dydx-airdrop.json index 9217af847..fadf7cd61 100644 --- a/contracts/dydx-airdrop/schema/dydx-airdrop.json +++ b/contracts/dydx-airdrop/schema/dydx-airdrop.json @@ -7,39 +7,47 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "addresses", "admin", "airdrop_amount", + "airdrop_count_limit", "claim_msg_plaintext", + "members", "minter_address", - "per_address_limit", + "name_collection_address", + "name_discount_wl_address", "whitelist_code_id" ], "properties": { - "addresses": { - "type": "array", - "items": { - "type": "string" - } - }, "admin": { - "$ref": "#/definitions/Addr" + "type": "string" }, "airdrop_amount": { "type": "integer", "format": "uint128", "minimum": 0.0 }, + "airdrop_count_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, "claim_msg_plaintext": { "type": "string" }, + "members": { + "type": "array", + "items": { + "$ref": "#/definitions/Member" + } + }, "minter_address": { - "$ref": "#/definitions/Addr" + "type": "string" }, - "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 + "name_collection_address": { + "type": "string" + }, + "name_discount_wl_address": { + "type": "string" }, "whitelist_code_id": { "type": "integer", @@ -49,9 +57,23 @@ }, "additionalProperties": false, "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" + "Member": { + "type": "object", + "required": [ + "address", + "mint_count" + ], + "properties": { + "address": { + "type": "string" + }, + "mint_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false } } }, @@ -59,6 +81,31 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ + { + "type": "object", + "required": [ + "register" + ], + "properties": { + "register": { + "type": "object", + "required": [ + "eth_address", + "eth_sig" + ], + "properties": { + "eth_address": { + "type": "string" + }, + "eth_sig": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/ts/src/DydxAirdrop.client.ts b/ts/src/DydxAirdrop.client.ts new file mode 100644 index 000000000..a9d3169a0 --- /dev/null +++ b/ts/src/DydxAirdrop.client.ts @@ -0,0 +1,107 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { Coin, StdFee } from "@cosmjs/amino"; +import { InstantiateMsg, Member, ExecuteMsg, QueryMsg, Boolean, Addr } from "./DydxAirdrop.types"; +export interface DydxAirdropReadOnlyInterface { + contractAddress: string; + airdropEligible: ({ + ethAddress + }: { + ethAddress: string; + }) => Promise; + getMinter: () => Promise; +} +export class DydxAirdropQueryClient implements DydxAirdropReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.airdropEligible = this.airdropEligible.bind(this); + this.getMinter = this.getMinter.bind(this); + } + + airdropEligible = async ({ + ethAddress + }: { + ethAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + airdrop_eligible: { + eth_address: ethAddress + } + }); + }; + getMinter = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_minter: {} + }); + }; +} +export interface DydxAirdropInterface extends DydxAirdropReadOnlyInterface { + contractAddress: string; + sender: string; + register: ({ + ethAddress, + ethSig + }: { + ethAddress: string; + ethSig: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + claimAirdrop: ({ + ethAddress, + ethSig + }: { + ethAddress: string; + ethSig: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class DydxAirdropClient extends DydxAirdropQueryClient implements DydxAirdropInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.register = this.register.bind(this); + this.claimAirdrop = this.claimAirdrop.bind(this); + } + + register = async ({ + ethAddress, + ethSig + }: { + ethAddress: string; + ethSig: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + register: { + eth_address: ethAddress, + eth_sig: ethSig + } + }, fee, memo, _funds); + }; + claimAirdrop = async ({ + ethAddress, + ethSig + }: { + ethAddress: string; + ethSig: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + claim_airdrop: { + eth_address: ethAddress, + eth_sig: ethSig + } + }, fee, memo, _funds); + }; +} \ No newline at end of file diff --git a/ts/src/DydxAirdrop.types.ts b/ts/src/DydxAirdrop.types.ts new file mode 100644 index 000000000..652656f2e --- /dev/null +++ b/ts/src/DydxAirdrop.types.ts @@ -0,0 +1,41 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export interface InstantiateMsg { + admin: string; + airdrop_amount: number; + airdrop_count_limit: number; + claim_msg_plaintext: string; + members: Member[]; + minter_address: string; + name_collection_address: string; + name_discount_wl_address: string; + whitelist_code_id: number; +} +export interface Member { + address: string; + mint_count: number; +} +export type ExecuteMsg = { + register: { + eth_address: string; + eth_sig: string; + }; +} | { + claim_airdrop: { + eth_address: string; + eth_sig: string; + }; +}; +export type QueryMsg = { + airdrop_eligible: { + eth_address: string; + }; +} | { + get_minter: {}; +}; +export type Boolean = boolean; +export type Addr = string; \ No newline at end of file From ceb1aa825ff249da277cc66c5963a99565c07053 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Mon, 18 Mar 2024 12:14:39 +0300 Subject: [PATCH 27/42] Update airdrop & whitelist immutable flex contract instantiation parameters --- .../dydx-airdrop/schema/raw/execute.json | 25 ++ .../dydx-airdrop/schema/raw/instantiate.json | 56 +++-- contracts/dydx-airdrop/src/msg.rs | 4 +- contracts/dydx-airdrop/src/query.rs | 2 +- contracts/dydx-airdrop/src/validation.rs | 11 +- .../setup_collection_whitelist_flex.rs | 2 +- .../dydx_airdrop/constants/claim_constants.rs | 1 + .../setup/collection_whitelist_helpers.rs | 6 +- .../src/dydx_airdrop/setup/execute_msg.rs | 14 +- .../setup/mock_whitelist_contract.rs | 2 +- .../src/dydx_airdrop/setup/test_msgs.rs | 13 +- .../src/dydx_airdrop/tests/test_claim.rs | 220 ++++++++++-------- .../tests/test_collection_whitelist.rs | 45 ++-- .../tests/test_immutable_whitelist.rs | 98 ++++---- 14 files changed, 302 insertions(+), 197 deletions(-) diff --git a/contracts/dydx-airdrop/schema/raw/execute.json b/contracts/dydx-airdrop/schema/raw/execute.json index 78ab6b551..41a752849 100644 --- a/contracts/dydx-airdrop/schema/raw/execute.json +++ b/contracts/dydx-airdrop/schema/raw/execute.json @@ -2,6 +2,31 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", "oneOf": [ + { + "type": "object", + "required": [ + "register" + ], + "properties": { + "register": { + "type": "object", + "required": [ + "eth_address", + "eth_sig" + ], + "properties": { + "eth_address": { + "type": "string" + }, + "eth_sig": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ diff --git a/contracts/dydx-airdrop/schema/raw/instantiate.json b/contracts/dydx-airdrop/schema/raw/instantiate.json index d7e7e85ad..464bfc25b 100644 --- a/contracts/dydx-airdrop/schema/raw/instantiate.json +++ b/contracts/dydx-airdrop/schema/raw/instantiate.json @@ -3,39 +3,47 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "addresses", "admin", "airdrop_amount", + "airdrop_count_limit", "claim_msg_plaintext", + "members", "minter_address", - "per_address_limit", + "name_collection_address", + "name_discount_wl_address", "whitelist_code_id" ], "properties": { - "addresses": { - "type": "array", - "items": { - "type": "string" - } - }, "admin": { - "$ref": "#/definitions/Addr" + "type": "string" }, "airdrop_amount": { "type": "integer", "format": "uint128", "minimum": 0.0 }, + "airdrop_count_limit": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, "claim_msg_plaintext": { "type": "string" }, + "members": { + "type": "array", + "items": { + "$ref": "#/definitions/Member" + } + }, "minter_address": { - "$ref": "#/definitions/Addr" + "type": "string" }, - "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 + "name_collection_address": { + "type": "string" + }, + "name_discount_wl_address": { + "type": "string" }, "whitelist_code_id": { "type": "integer", @@ -45,9 +53,23 @@ }, "additionalProperties": false, "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" + "Member": { + "type": "object", + "required": [ + "address", + "mint_count" + ], + "properties": { + "address": { + "type": "string" + }, + "mint_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false } } } diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index a13549bf2..ce2829d56 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -4,12 +4,12 @@ use whitelist_immutable_flex::msg::Member; #[cw_serde] pub struct InstantiateMsg { - pub admin: Addr, + pub admin: String, pub claim_msg_plaintext: String, pub airdrop_amount: u128, pub members: Vec, pub whitelist_code_id: u64, - pub minter_address: Addr, + pub minter_address: String, pub name_discount_wl_address: String, pub name_collection_address: String, pub airdrop_count_limit: u32, diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index 25e4bec57..d4bece88e 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -59,7 +59,7 @@ pub fn query_mint_count(deps: &DepsMut, eth_address: String) -> StdResult { })?; let member_response: MemberResponse = deps.querier.query(&cosmwasm_std::QueryRequest::Wasm( cosmwasm_std::WasmQuery::Smart { - contract_addr: whitelist_address.into(), + contract_addr: whitelist_address, msg: to_json_binary(&whitelist_immutable_flex::msg::QueryMsg::Member { address: eth_address, })?, diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index 2030e707d..4e3f7ac7c 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -131,11 +131,10 @@ pub fn validate_collection_mint(deps: &DepsMut, info: MessageInfo) -> Result<(), limit: None, }, )?; - return if tokens_response.tokens.len() == 0 { - Err(ContractError::CollectionNotMinted {}) - } else { - Ok(()) - }; + if tokens_response.tokens.is_empty() { + return Err(ContractError::CollectionNotMinted {}); + } + Ok(()) } pub fn validate_name_mint_and_association( @@ -152,7 +151,7 @@ pub fn validate_name_mint_and_association( limit: None, }, )?; - if tokens_response.tokens.len() == 0 { + if tokens_response.tokens.is_empty() { return Err(ContractError::NameNotMinted {}); }; let _associated_name: String = deps.querier.query_wasm_smart( diff --git a/test-suite/src/common_setup/setup_collection_whitelist_flex.rs b/test-suite/src/common_setup/setup_collection_whitelist_flex.rs index abe182c7b..ae383f56b 100644 --- a/test-suite/src/common_setup/setup_collection_whitelist_flex.rs +++ b/test-suite/src/common_setup/setup_collection_whitelist_flex.rs @@ -94,7 +94,7 @@ pub fn configure_collection_whitelist_flex( // Update whitelist_expiration fails if not admin let wl_msg = sg_whitelist_flex::msg::ExecuteMsg::UpdateEndTime(AFTER_GENESIS_TIME); router - .execute_contract(buyer, whitelist_addr.clone(), &wl_msg, &[]) + .execute_contract(buyer, whitelist_flex_addr.clone(), &wl_msg, &[]) .unwrap_err(); // Update whitelist_expiration succeeds when from admin diff --git a/test-suite/src/dydx_airdrop/constants/claim_constants.rs b/test-suite/src/dydx_airdrop/constants/claim_constants.rs index dc8f2a909..d72b6dcbb 100644 --- a/test-suite/src/dydx_airdrop/constants/claim_constants.rs +++ b/test-suite/src/dydx_airdrop/constants/claim_constants.rs @@ -2,6 +2,7 @@ pub const OWNER: &str = "admin0001"; pub const MOCK_AIRDROP_ADDR_STR: &str = "contract3"; pub const MOCK_MINTER_ADDR_STR: &str = "contract1"; pub const MOCK_NAME_DISCOUNT_WL_ADDR_STR: &str = "contract2"; +pub const MOCK_NAME_COLLECTION_ADDR: &str = "contract3"; pub const STARGAZE_WALLET_01: &str = "0xstargaze_wallet_01"; pub const STARGAZE_WALLET_02: &str = "0xstargaze_wallet_02"; pub const CONFIG_PLAINTEXT: &str = "My Stargaze address is {wallet} and I want a Winter Pal."; diff --git a/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs index deb28a1f9..dcd1bff4e 100644 --- a/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs +++ b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs @@ -6,7 +6,7 @@ use cosmwasm_std::{coins, Addr}; use cw_multi_test::{BankSudo, Executor, SudoMsg}; use sg_multi_test::StargazeApp; -extern crate whitelist_immutable; +extern crate whitelist_immutable_flex; pub fn update_admin_for_whitelist( app: &mut StargazeApp, @@ -15,7 +15,7 @@ pub fn update_admin_for_whitelist( target_contract: Addr, ) { // add airdrop contract as admin on whitelist - let update_admin_message = sg_whitelist::msg::ExecuteMsg::UpdateAdmins { + let update_admin_message = sg_whitelist_flex::msg::ExecuteMsg::UpdateAdmins { admins: vec![target_admin.to_string()], }; let _ = app.execute_contract(sender, target_contract, &update_admin_message, &[]); @@ -71,4 +71,4 @@ pub fn execute_mint_success(app: &mut StargazeApp, sender: Addr, minter_addr: Ad &coins(WHITELIST_AMOUNT, NATIVE_DENOM), ); assert!(res.is_ok()) -} +} \ No newline at end of file diff --git a/test-suite/src/dydx_airdrop/setup/execute_msg.rs b/test-suite/src/dydx_airdrop/setup/execute_msg.rs index e6f05c4b9..356835278 100644 --- a/test-suite/src/dydx_airdrop/setup/execute_msg.rs +++ b/test-suite/src/dydx_airdrop/setup/execute_msg.rs @@ -14,12 +14,13 @@ use sg_multi_test::StargazeApp; use sg_std::NATIVE_DENOM; pub fn instantiate_contract(params: InstantiateParams) -> Result { - let addresses = params.addresses; + let members = params.members; let minter_address = params.minter_address; let admin_account = params.admin_account; let funds_amount = params.funds_amount; - let per_address_limit = params.per_address_limit; let claim_msg_plaintext = params.claim_msg_plaintext; + let airdrop_amount = params.airdrop_amount; + let airdrop_count_limit = params.airdrop_count_limit; params .app .sudo(SudoMsg::Bank({ @@ -37,14 +38,15 @@ pub fn instantiate_contract(params: InstantiateParams) -> Result { - pub addresses: Vec, + pub members: Vec, pub funds_amount: u128, pub expected_airdrop_contract_id: u64, - pub minter_address: Addr, - pub admin_account: Addr, + pub minter_address: String, + pub admin_account: String, pub app: &'a mut StargazeApp, - pub per_address_limit: u32, + pub name_discount_wl_address: String, + pub name_collection_address: String, + pub airdrop_count_limit: u32, pub claim_msg_plaintext: String, - pub name_discount_wl_address: Addr, + pub airdrop_amount: u128, } diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index ca92245e3..f8700b238 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -13,16 +13,14 @@ use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::dydx_airdrop::constants::claim_constants::{ - CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, - NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, -}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02}; use crate::dydx_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, }; use dydx_airdrop::contract::INSTANTIATION_FEE; +use whitelist_immutable_flex::msg::Member; fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minter_addr: Addr) { let query_msg = QueryMsg::GetMinter {}; @@ -36,20 +34,22 @@ fn query_minter_as_expected(app: &mut StargazeApp, airdrop_contract: Addr, minte #[test] fn test_instantiate() { let mut app = custom_mock_app(); - let minter_address = Addr::unchecked("contract1"); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - addresses: vec![eth_addr_str], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, - admin_account: Addr::unchecked(OWNER), + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address: "".to_string(), + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); } @@ -58,20 +58,23 @@ fn test_instantiate() { fn test_instantiate_plaintext_too_long() { let long_config_plaintext: String = String::from_utf8(vec![b'X'; 1001]).unwrap() + " {wallet}"; let mut app = custom_mock_app(); - let minter_address = Addr::unchecked("contract1"); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - addresses: vec![eth_addr_str], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, - admin_account: Addr::unchecked(OWNER), + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: long_config_plaintext, name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; let res = instantiate_contract(params).unwrap_err(); assert_eq!( @@ -84,20 +87,23 @@ fn test_instantiate_plaintext_too_long() { fn test_instantiate_plaintext_missing_wallet() { let plaintext_config_no_wallet = "This message doesn't have wallet string".to_string(); let mut app = custom_mock_app(); - let minter_address = Addr::unchecked("contract1"); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - addresses: vec![eth_addr_str], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, - admin_account: Addr::unchecked(OWNER), + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: plaintext_config_no_wallet, name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; let res = instantiate_contract(params).unwrap_err(); assert_eq!( @@ -112,25 +118,29 @@ fn test_airdrop_eligible_query() { let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; + instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let query_msg = QueryMsg::AirdropEligible { - eth_address: eth_addr_str, + eth_address: eth_addr_str.clone(), }; let result: bool = app .wrap() @@ -154,25 +164,28 @@ fn test_valid_eth_sig_claim() { let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let claim_message = ExecuteMsg::ClaimAirdrop { - eth_address: eth_addr_str, + eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, }; let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); @@ -205,23 +218,26 @@ fn test_invalid_eth_sig_claim() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let claim_message = ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str_2, @@ -243,23 +259,26 @@ fn test_can_not_claim_twice() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let claim_message = ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, @@ -303,23 +322,26 @@ fn test_claim_one_valid_airdrop() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - name_discount_wl_address: name_discount_wl_address.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let balances = app .wrap() .query_all_balances(stargaze_wallet_01.clone()) @@ -327,7 +349,7 @@ fn test_claim_one_valid_airdrop() { assert_eq!(balances, []); let claim_message = ExecuteMsg::ClaimAirdrop { - eth_address: eth_addr_str, + eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, }; let _ = execute_contract_with_msg( @@ -355,23 +377,26 @@ fn test_claim_twice_receive_funds_once() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - name_discount_wl_address: name_discount_wl_address.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let balances = app .wrap() .query_all_balances(stargaze_wallet_01.clone()) @@ -422,23 +447,26 @@ fn test_ineligible_does_not_receive_funds() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); let stargaze_wallet_02 = Addr::unchecked(STARGAZE_WALLET_02); let balances = app .wrap() @@ -481,20 +509,23 @@ fn test_one_eth_claim_two_stargaze_addresses_invalid() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str_1.clone()], + members: vec![Member {address: eth_addr_str_1, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); @@ -553,20 +584,23 @@ fn test_two_claims_allowed_success() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 2}], funds_amount: WHITELIST_AMOUNT * 2 + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 2, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), - name_discount_wl_address: name_discount_wl_address.clone(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); @@ -599,7 +633,7 @@ fn test_two_claims_allowed_success() { assert_eq!(balances, expected_balance); let claim_message = ExecuteMsg::ClaimAirdrop { - eth_address: eth_addr_str, + eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, }; let _ = execute_contract_with_msg( diff --git a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index bb3270b2d..3e877c47a 100644 --- a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,8 +1,6 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::dydx_airdrop::constants::claim_constants::{ - CONFIG_PLAINTEXT, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01, -}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER, STARGAZE_WALLET_01}; use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; @@ -19,27 +17,31 @@ use sg_std::GENESIS_MINT_START_TIME; extern crate whitelist_immutable; use crate::common_setup::templates::vending_minter_template; use dydx_airdrop::contract::INSTANTIATION_FEE; +use whitelist_immutable_flex::msg::Member; #[test] fn test_set_minter_contract_success() { let vt = vending_minter_template(1); let (mut app, creator) = (vt.router, vt.accts.creator); - let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let contract_admin = Addr::unchecked(creator); let params = InstantiateParams { - addresses: vec![eth_addr_str], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: contract_admin, + minter_address, + admin_account: contract_admin.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); let airdrop_contract = Addr::unchecked("contract3"); @@ -48,45 +50,48 @@ fn test_set_minter_contract_success() { .wrap() .query_wasm_smart(airdrop_contract, &query_msg) .unwrap(); - assert_eq!(result, minter_addr); + assert_eq!(result, minter_address); } #[test] fn test_claim_added_to_minter_whitelist() { let vt = vending_minter_template(1); let (mut app, creator, buyer) = (vt.router, vt.accts.creator, vt.accts.buyer); - let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let whitelist_addr = - configure_collection_whitelist(&mut app, creator.clone(), buyer, minter_addr.clone()); + configure_collection_whitelist(&mut app, creator.clone(), buyer, Addr::unchecked(minter_address.clone())); setup_block_time(&mut app, GENESIS_MINT_START_TIME, None); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let airdrop_contract = Addr::unchecked(AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses: vec![eth_addr_str.clone()], + members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 5, - minter_address: minter_addr.clone(), - admin_account: creator.clone(), + minter_address, + admin_account: creator.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); let stargaze_wallet_01 = Addr::unchecked(STARGAZE_WALLET_01); update_admin_for_whitelist(&mut app, creator, airdrop_contract.clone(), whitelist_addr); send_funds_to_address(&mut app, STARGAZE_WALLET_01, MINT_PRICE); - execute_mint_fail_not_on_whitelist(&mut app, minter_addr.clone()); + execute_mint_fail_not_on_whitelist(&mut app, Addr::unchecked(minter_address.clone())); execute_airdrop_claim( &mut app, - eth_addr_str, + eth_addr_str.clone(), eth_sig_str, stargaze_wallet_01.clone(), airdrop_contract, ); - execute_mint_success(&mut app, stargaze_wallet_01, minter_addr); + execute_mint_success(&mut app, stargaze_wallet_01, Addr::unchecked(minter_address.clone())); } diff --git a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index 428ac7731..10765ef95 100644 --- a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -1,8 +1,5 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::dydx_airdrop::constants::claim_constants::{ - CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, - OWNER, -}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER}; use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; @@ -11,7 +8,9 @@ use crate::dydx_airdrop::setup::test_msgs::InstantiateParams; use cosmwasm_std::Addr; use dydx_airdrop::contract::INSTANTIATION_FEE; use dydx_airdrop::msg::QueryMsg; -use whitelist_immutable::helpers::WhitelistImmutableContract; +use whitelist_immutable_flex::helpers::WhitelistImmutableFlexContract; +use whitelist_immutable_flex::msg::Member; +use whitelist_immutable_flex::state::Config; #[test] fn test_instantiate_with_addresses() { @@ -23,20 +22,23 @@ fn test_instantiate_with_addresses() { let mut app = { custom_mock_app }(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - addresses, + members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); @@ -69,24 +71,27 @@ fn test_whitelist_immutable_address_limit() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - addresses, + members: vec![Member {address: addresses[0].clone(), mint_count: 20}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - let whitelist_immutable = Addr::unchecked("contract4"); - let res: u32 = WhitelistImmutableContract(whitelist_immutable) - .per_address_limit(&app.wrap()) + let whitelist_immutable_flex = Addr::unchecked("contract4"); + let res: u32 = WhitelistImmutableFlexContract(whitelist_immutable_flex) + .mint_count(&app.wrap(), "addr1".to_string()) .unwrap(); assert_eq!(res, 20); } @@ -101,23 +106,26 @@ fn test_whitelist_immutable_address_count() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - addresses, + members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); - let res: u64 = WhitelistImmutableContract(whitelist_immutable) + let res: u64 = WhitelistImmutableFlexContract(whitelist_immutable) .address_count(&app.wrap()) .unwrap(); assert_eq!(res, 3); @@ -133,28 +141,31 @@ fn test_whitelist_immutable_address_includes() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - addresses, + members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); - let res: bool = WhitelistImmutableContract(whitelist_immutable.clone()) + let res: bool = WhitelistImmutableFlexContract(whitelist_immutable.clone()) .includes(&app.wrap(), "addr3".to_string()) .unwrap(); assert!(res); - let res: bool = WhitelistImmutableContract(whitelist_immutable) + let res: bool = WhitelistImmutableFlexContract(whitelist_immutable) .includes(&app.wrap(), "nonsense".to_string()) .unwrap(); assert!(!res); @@ -170,23 +181,26 @@ fn test_whitelist_immutable_address_config() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); - let name_discount_wl_address = Addr::unchecked(MOCK_NAME_DISCOUNT_WL_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - addresses, + members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr, - admin_account: Addr::unchecked(OWNER), + minter_address, + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 20, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); let whitelist_immutable = Addr::unchecked("contract4"); - let res: whitelist_immutable::state::Config = WhitelistImmutableContract(whitelist_immutable) + let res: Config = WhitelistImmutableFlexContract(whitelist_immutable) .config(&app.wrap()) .unwrap(); let expected_config = whitelist_immutable::state::Config { From b57450c4329253d31611c6657d22251db2f9f4c0 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Mon, 18 Mar 2024 12:30:43 +0300 Subject: [PATCH 28/42] Address issues in test code (tests failing pre-update) --- .../src/dydx_airdrop/setup/execute_msg.rs | 1 - .../src/dydx_airdrop/setup/test_msgs.rs | 1 - .../src/dydx_airdrop/tests/test_claim.rs | 30 +++++++++---------- .../tests/test_collection_whitelist.rs | 8 ++--- .../tests/test_immutable_whitelist.rs | 3 +- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/test-suite/src/dydx_airdrop/setup/execute_msg.rs b/test-suite/src/dydx_airdrop/setup/execute_msg.rs index 356835278..ec491754d 100644 --- a/test-suite/src/dydx_airdrop/setup/execute_msg.rs +++ b/test-suite/src/dydx_airdrop/setup/execute_msg.rs @@ -1,5 +1,4 @@ use crate::dydx_airdrop::constants::claim_constants::OWNER; -use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::{ common_setup::contract_boxes::{contract_dydx_airdrop, contract_whitelist_immutable}, dydx_airdrop::setup::test_msgs::InstantiateParams, diff --git a/test-suite/src/dydx_airdrop/setup/test_msgs.rs b/test-suite/src/dydx_airdrop/setup/test_msgs.rs index f7ed2c2cd..effa1b4f4 100644 --- a/test-suite/src/dydx_airdrop/setup/test_msgs.rs +++ b/test-suite/src/dydx_airdrop/setup/test_msgs.rs @@ -1,4 +1,3 @@ -use cosmwasm_std::Addr; use sg_multi_test::StargazeApp; use whitelist_immutable_flex::msg::Member; diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index f8700b238..8e607a901 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -124,10 +124,10 @@ fn test_airdrop_eligible_query() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -170,10 +170,10 @@ fn test_valid_eth_sig_claim() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -224,10 +224,10 @@ fn test_invalid_eth_sig_claim() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -265,10 +265,10 @@ fn test_can_not_claim_twice() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -328,10 +328,10 @@ fn test_claim_one_valid_airdrop() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -383,10 +383,10 @@ fn test_claim_twice_receive_funds_once() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -456,7 +456,7 @@ fn test_ineligible_does_not_receive_funds() { members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: OWNER.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -515,7 +515,7 @@ fn test_one_eth_claim_two_stargaze_addresses_invalid() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str_1, mint_count: 1}], + members: vec![Member {address: eth_addr_str_1.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -590,7 +590,7 @@ fn test_two_claims_allowed_success() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 2}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 2}], funds_amount: WHITELIST_AMOUNT * 2 + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, diff --git a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index 3e877c47a..15a82e95c 100644 --- a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,6 +1,6 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01}; use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; @@ -34,7 +34,7 @@ fn test_set_minter_contract_success() { members: vec![Member {address: eth_addr_str, mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address, + minter_address: minter_address.clone(), admin_account: contract_admin.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), @@ -68,10 +68,10 @@ fn test_claim_added_to_minter_whitelist() { let airdrop_contract = Addr::unchecked(AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 5, - minter_address, + minter_address: minter_address.clone(), admin_account: creator.to_string(), app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), diff --git a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index 10765ef95..f1e433ce2 100644 --- a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -203,9 +203,8 @@ fn test_whitelist_immutable_address_config() { let res: Config = WhitelistImmutableFlexContract(whitelist_immutable) .config(&app.wrap()) .unwrap(); - let expected_config = whitelist_immutable::state::Config { + let expected_config = whitelist_immutable_flex::state::Config { admin: Addr::unchecked("contract3"), - per_address_limit: 20, mint_discount_bps: Some(0), }; assert_eq!(res, expected_config); From 5ee3affa94271b444e07849b22385dd4d4b37173 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Tue, 19 Mar 2024 21:47:17 +0300 Subject: [PATCH 29/42] Address issues induced by the merge --- Cargo.toml | 1 + contracts/dydx-airdrop/src/claim_airdrop.rs | 108 +------------- contracts/dydx-airdrop/src/validation.rs | 11 ++ .../setup/collection_whitelist_helpers.rs | 2 +- .../src/dydx_airdrop/tests/test_claim.rs | 134 ++++++++++++++---- .../tests/test_collection_whitelist.rs | 29 +++- .../tests/test_immutable_whitelist.rs | 80 ++++++++++- 7 files changed, 218 insertions(+), 147 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b43e38405..5d2da85d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "contracts/factories/*", "contracts/minters/*", "contracts/whitelists/*", + "contracts/dydx-airdrop", "test-suite/", "e2e", ] diff --git a/contracts/dydx-airdrop/src/claim_airdrop.rs b/contracts/dydx-airdrop/src/claim_airdrop.rs index 94b1283fd..2cfd19307 100644 --- a/contracts/dydx-airdrop/src/claim_airdrop.rs +++ b/contracts/dydx-airdrop/src/claim_airdrop.rs @@ -20,13 +20,10 @@ pub fn claim_airdrop( return Err(ContractError::AirdropCountLimitExceeded {}); } - let eth_address_lower = eth_address.to_ascii_lowercase(); - validation::assert_lower_case(eth_address_lower.clone())?; - validate_claim( &deps, info.clone(), - eth_address_lower.clone(), + eth_address.clone(), eth_sig, config.clone(), )?; @@ -38,106 +35,3 @@ pub fn claim_airdrop( HAS_CLAIMED.save(deps.storage, ð_address, &true)?; Ok(res.add_attribute("claimed_amount", config.airdrop_amount.to_string())) } - -mod validation { - use super::*; - use cosmwasm_std::StdError; - use ethereum_verify::verify_ethereum_text; - - use crate::{ - query::{query_airdrop_is_eligible, query_per_address_limit}, - state::Config, - }; - - pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { - str::replace( - &config.claim_msg_plaintext, - "{wallet}", - info.sender.as_ref(), - ) - } - - pub fn assert_lower_case(eth_address: String) -> Result<(), ContractError> { - match eth_address.to_lowercase() == eth_address { - true => Ok(()), - false => Err(ContractError::EthAddressShouldBeLower { - address: eth_address, - }), - } - } - - pub fn validate_claim( - deps: &DepsMut, - info: MessageInfo, - eth_address: String, - eth_sig: String, - config: Config, - ) -> Result<(), ContractError> { - assert_lower_case(eth_address.clone())?; - validate_is_eligible(deps, eth_address.clone())?; - validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; - validate_mints_remaining(deps, ð_address)?; - Ok(()) - } - - fn validate_is_eligible(deps: &DepsMut, eth_address: String) -> Result<(), ContractError> { - let eligible = query_airdrop_is_eligible(deps.as_ref(), eth_address.clone())?; - match eligible { - true => Ok(()), - false => Err(ContractError::AddressNotEligible { - address: eth_address, - }), - } - } - - fn validate_eth_sig( - deps: &DepsMut, - info: MessageInfo, - eth_address: String, - eth_sig: String, - config: Config, - ) -> Result<(), ContractError> { - let valid_eth_sig = - validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; - match valid_eth_sig { - true => Ok(()), - false => Err(ContractError::AddressNotEligible { - address: eth_address, - }), - } - } - - pub fn validate_mints_remaining( - deps: &DepsMut, - eth_address: &str, - ) -> Result<(), ContractError> { - let mint_count = ADDRS_TO_MINT_COUNT.load(deps.storage, eth_address); - let mint_count = mint_count.unwrap_or(0); - let per_address_limit = query_per_address_limit(&deps.as_ref())?; - if mint_count < per_address_limit { - Ok(()) - } else { - Err(ContractError::MintCountReached { - address: eth_address.to_string(), - }) - } - } - - pub fn validate_ethereum_text( - deps: &DepsMut, - info: MessageInfo, - config: &Config, - eth_sig: String, - eth_address: String, - ) -> StdResult { - let plaintext_msg = compute_plaintext_msg(config, info); - match hex::decode(eth_sig.clone()) { - Ok(eth_sig_hex) => { - verify_ethereum_text(deps.as_ref(), &plaintext_msg, ð_sig_hex, ð_address) - } - Err(_) => Err(StdError::InvalidHex { - msg: format!("Could not decode {eth_sig}"), - }), - } - } -} diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index 4e3f7ac7c..c58a401ff 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -67,6 +67,15 @@ pub fn compute_plaintext_msg(config: &Config, info: MessageInfo) -> String { ) } +pub fn assert_lower_case(eth_address: String) -> Result<(), ContractError> { + match eth_address.to_lowercase() == eth_address { + true => Ok(()), + false => Err(ContractError::EthAddressShouldBeLower { + address: eth_address, + }), + } +} + pub fn validate_registration( deps: &DepsMut, info: MessageInfo, @@ -74,6 +83,7 @@ pub fn validate_registration( eth_sig: String, config: Config, ) -> Result<(), ContractError> { + assert_lower_case(eth_address.clone())?; validate_is_eligible(deps, eth_address.clone())?; validate_eth_sig(deps, info, eth_address.clone(), eth_sig, config)?; check_previous_registration(deps, ð_address)?; @@ -87,6 +97,7 @@ pub fn validate_claim( eth_sig: String, config: Config, ) -> Result<(), ContractError> { + assert_lower_case(eth_address.clone())?; validate_is_eligible(deps, eth_address.clone())?; validate_eth_sig(deps, info.clone(), eth_address.clone(), eth_sig, config)?; check_previous_claim(deps, ð_address.clone())?; diff --git a/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs index dcd1bff4e..461f47eac 100644 --- a/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs +++ b/test-suite/src/dydx_airdrop/setup/collection_whitelist_helpers.rs @@ -71,4 +71,4 @@ pub fn execute_mint_success(app: &mut StargazeApp, sender: Addr, minter_addr: Ad &coins(WHITELIST_AMOUNT, NATIVE_DENOM), ); assert!(res.is_ok()) -} \ No newline at end of file +} diff --git a/test-suite/src/dydx_airdrop/tests/test_claim.rs b/test-suite/src/dydx_airdrop/tests/test_claim.rs index 206ef2eeb..f51fefb48 100644 --- a/test-suite/src/dydx_airdrop/tests/test_claim.rs +++ b/test-suite/src/dydx_airdrop/tests/test_claim.rs @@ -13,7 +13,10 @@ use ethers_core::rand::thread_rng; use ethers_signers::{LocalWallet, Signer}; use sg_multi_test::StargazeApp; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, + MOCK_NAME_DISCOUNT_WL_ADDR_STR, NATIVE_DENOM, OWNER, STARGAZE_WALLET_01, STARGAZE_WALLET_02, +}; use crate::dydx_airdrop::setup::execute_msg::{ execute_contract_error_with_msg, execute_contract_with_msg, instantiate_contract, @@ -36,10 +39,14 @@ fn test_instantiate() { let mut app = custom_mock_app(); let minter_address = MOCK_MINTER_ADDR_STR.to_string(); let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member { + address: eth_addr_str, + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, @@ -47,7 +54,7 @@ fn test_instantiate() { app: &mut app, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), name_discount_wl_address, - name_collection_address: "".to_string(), + name_collection_address, airdrop_count_limit: 500, airdrop_amount: WHITELIST_AMOUNT, }; @@ -64,7 +71,10 @@ fn test_instantiate_plaintext_too_long() { let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member { + address: eth_addr_str, + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, @@ -93,7 +103,10 @@ fn test_instantiate_plaintext_missing_wallet() { let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, _, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member { + address: eth_addr_str, + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 1, minter_address, @@ -124,7 +137,10 @@ fn test_airdrop_eligible_query() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -138,7 +154,11 @@ fn test_airdrop_eligible_query() { }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let query_msg = QueryMsg::AirdropEligible { eth_address: eth_addr_str.clone(), }; @@ -170,7 +190,10 @@ fn test_valid_eth_sig_claim() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -183,7 +206,11 @@ fn test_valid_eth_sig_claim() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let claim_message = ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, @@ -224,7 +251,10 @@ fn test_invalid_eth_sig_claim() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -237,7 +267,11 @@ fn test_invalid_eth_sig_claim() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let claim_message = ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str_2, @@ -265,7 +299,10 @@ fn test_can_not_claim_twice() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -278,7 +315,11 @@ fn test_can_not_claim_twice() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let claim_message = ExecuteMsg::ClaimAirdrop { eth_address: eth_addr_str.clone(), eth_sig: eth_sig_str, @@ -328,7 +369,10 @@ fn test_claim_one_valid_airdrop() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -341,7 +385,11 @@ fn test_claim_one_valid_airdrop() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let balances = app .wrap() .query_all_balances(stargaze_wallet_01.clone()) @@ -383,7 +431,10 @@ fn test_claim_twice_receive_funds_once() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -396,7 +447,11 @@ fn test_claim_twice_receive_funds_once() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let balances = app .wrap() .query_all_balances(stargaze_wallet_01.clone()) @@ -453,7 +508,10 @@ fn test_ineligible_does_not_receive_funds() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member { + address: eth_addr_str, + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -466,7 +524,11 @@ fn test_ineligible_does_not_receive_funds() { airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), Addr::unchecked(&minter_address)); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let stargaze_wallet_02 = Addr::unchecked(STARGAZE_WALLET_02); let balances = app .wrap() @@ -515,7 +577,10 @@ fn test_one_eth_claim_two_stargaze_addresses_invalid() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str_1.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str_1.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -590,7 +655,10 @@ fn test_two_claims_allowed_success() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 2}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 2, + }], funds_amount: WHITELIST_AMOUNT * 2 + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -661,7 +729,9 @@ fn test_claim_converts_to_lowercase() { let mut app = custom_mock_app(); configure_mock_minter_with_mock_whitelist(&mut app); - let minter_addr = Addr::unchecked(MOCK_MINTER_ADDR_STR); + let minter_address = MOCK_MINTER_ADDR_STR.to_string(); + let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); + let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let mut mixed_case = vec![]; @@ -677,17 +747,27 @@ fn test_claim_converts_to_lowercase() { let mixed_case_eth_addr: String = mixed_case.into_iter().collect(); let params = InstantiateParams { - addresses: vec![mixed_case_eth_addr.clone()], + members: vec![Member { + address: mixed_case_eth_addr.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, - minter_address: minter_addr.clone(), - admin_account: Addr::unchecked(OWNER), + minter_address: minter_address.clone(), + admin_account: OWNER.to_string(), app: &mut app, - per_address_limit: 1, claim_msg_plaintext: CONFIG_PLAINTEXT.to_string(), + name_discount_wl_address, + name_collection_address, + airdrop_count_limit: 500, + airdrop_amount: WHITELIST_AMOUNT, }; instantiate_contract(params).unwrap(); - query_minter_as_expected(&mut app, airdrop_contract.clone(), minter_addr); + query_minter_as_expected( + &mut app, + airdrop_contract.clone(), + Addr::unchecked(&minter_address), + ); let balances = app .wrap() .query_all_balances(stargaze_wallet_01.clone()) diff --git a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs index 15a82e95c..fe0ca73ff 100644 --- a/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_collection_whitelist.rs @@ -1,6 +1,9 @@ use crate::common_setup::setup_accounts_and_block::setup_block_time; use crate::common_setup::setup_collection_whitelist::configure_collection_whitelist; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, + MOCK_NAME_DISCOUNT_WL_ADDR_STR, STARGAZE_WALLET_01, +}; use crate::dydx_airdrop::constants::collection_constants::{ AIRDROP_ADDR_STR, MINT_PRICE, WHITELIST_AMOUNT, }; @@ -31,7 +34,10 @@ fn test_set_minter_contract_success() { let contract_admin = Addr::unchecked(creator); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str, mint_count: 1}], + members: vec![Member { + address: eth_addr_str, + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address: minter_address.clone(), @@ -60,15 +66,22 @@ fn test_claim_added_to_minter_whitelist() { let minter_address = MOCK_MINTER_ADDR_STR.to_string(); let name_discount_wl_address = MOCK_NAME_DISCOUNT_WL_ADDR_STR.to_string(); let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); - let whitelist_addr = - configure_collection_whitelist(&mut app, creator.clone(), buyer, Addr::unchecked(minter_address.clone())); + let whitelist_addr = configure_collection_whitelist( + &mut app, + creator.clone(), + buyer, + Addr::unchecked(minter_address.clone()), + ); setup_block_time(&mut app, GENESIS_MINT_START_TIME, None); let claim_plaintext = &get_msg_plaintext(STARGAZE_WALLET_01.to_string()); let (_, eth_sig_str, _, eth_addr_str) = get_wallet_and_sig(claim_plaintext.clone()); let airdrop_contract = Addr::unchecked(AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: eth_addr_str.clone(), mint_count: 1}], + members: vec![Member { + address: eth_addr_str.clone(), + mint_count: 1, + }], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 5, minter_address: minter_address.clone(), @@ -93,5 +106,9 @@ fn test_claim_added_to_minter_whitelist() { stargaze_wallet_01.clone(), airdrop_contract, ); - execute_mint_success(&mut app, stargaze_wallet_01, Addr::unchecked(minter_address.clone())); + execute_mint_success( + &mut app, + stargaze_wallet_01, + Addr::unchecked(minter_address.clone()), + ); } diff --git a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs index f1e433ce2..aabbf1404 100644 --- a/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs +++ b/test-suite/src/dydx_airdrop/tests/test_immutable_whitelist.rs @@ -1,5 +1,8 @@ use crate::common_setup::contract_boxes::custom_mock_app; -use crate::dydx_airdrop::constants::claim_constants::{CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER}; +use crate::dydx_airdrop::constants::claim_constants::{ + CONFIG_PLAINTEXT, MOCK_AIRDROP_ADDR_STR, MOCK_MINTER_ADDR_STR, MOCK_NAME_COLLECTION_ADDR, + MOCK_NAME_DISCOUNT_WL_ADDR_STR, OWNER, +}; use crate::dydx_airdrop::constants::collection_constants::WHITELIST_AMOUNT; use crate::dydx_airdrop::setup::configure_mock_minter::configure_mock_minter_with_mock_whitelist; use crate::dydx_airdrop::setup::execute_msg::instantiate_contract; @@ -28,7 +31,20 @@ fn test_instantiate_with_addresses() { let airdrop_contract = Addr::unchecked(MOCK_AIRDROP_ADDR_STR); let params = InstantiateParams { - members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], + members: vec![ + Member { + address: addresses[0].clone(), + mint_count: 1, + }, + Member { + address: addresses[1].clone(), + mint_count: 1, + }, + Member { + address: addresses[2].clone(), + mint_count: 1, + }, + ], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -76,7 +92,20 @@ fn test_whitelist_immutable_address_limit() { let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - members: vec![Member {address: addresses[0].clone(), mint_count: 20}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], + members: vec![ + Member { + address: addresses[0].clone(), + mint_count: 20, + }, + Member { + address: addresses[1].clone(), + mint_count: 1, + }, + Member { + address: addresses[2].clone(), + mint_count: 1, + }, + ], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -111,7 +140,20 @@ fn test_whitelist_immutable_address_count() { let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], + members: vec![ + Member { + address: addresses[0].clone(), + mint_count: 1, + }, + Member { + address: addresses[1].clone(), + mint_count: 1, + }, + Member { + address: addresses[2].clone(), + mint_count: 1, + }, + ], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -146,7 +188,20 @@ fn test_whitelist_immutable_address_includes() { let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], + members: vec![ + Member { + address: addresses[0].clone(), + mint_count: 1, + }, + Member { + address: addresses[1].clone(), + mint_count: 1, + }, + Member { + address: addresses[2].clone(), + mint_count: 1, + }, + ], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, @@ -186,7 +241,20 @@ fn test_whitelist_immutable_address_config() { let name_collection_address = MOCK_NAME_COLLECTION_ADDR.to_string(); let params = InstantiateParams { - members: vec![Member {address: addresses[0].clone(), mint_count: 1}, Member {address: addresses[1].clone(), mint_count: 1}, Member {address: addresses[2].clone(), mint_count: 1}], + members: vec![ + Member { + address: addresses[0].clone(), + mint_count: 1, + }, + Member { + address: addresses[1].clone(), + mint_count: 1, + }, + Member { + address: addresses[2].clone(), + mint_count: 1, + }, + ], funds_amount: WHITELIST_AMOUNT + INSTANTIATION_FEE, expected_airdrop_contract_id: 4, minter_address, From 32a527a172f56a88a1f5e111f3bb0de3f836096c Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 20 Mar 2024 18:01:43 +0300 Subject: [PATCH 30/42] Update error for invalid eth signature --- contracts/dydx-airdrop/src/error.rs | 3 +++ contracts/dydx-airdrop/src/validation.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 270b43383..5f79ad74e 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -40,6 +40,9 @@ pub enum ContractError { #[error("Address {address} is not eligible")] AddressNotEligible { address: String }, + #[error("Invalid Eth signature for address: {address}")] + InvalidEthSignature { address: String }, + #[error("Address {address} has already claimed all available mints")] MintCountReached { address: String }, diff --git a/contracts/dydx-airdrop/src/validation.rs b/contracts/dydx-airdrop/src/validation.rs index c58a401ff..a93ef92f0 100644 --- a/contracts/dydx-airdrop/src/validation.rs +++ b/contracts/dydx-airdrop/src/validation.rs @@ -126,7 +126,7 @@ fn validate_eth_sig( let valid_eth_sig = validate_ethereum_text(deps, info, &config, eth_sig, eth_address.clone())?; match valid_eth_sig { true => Ok(()), - false => Err(ContractError::AddressNotEligible { + false => Err(ContractError::InvalidEthSignature { address: eth_address, }), } From ee608b995dbf3a87959e18a5c30593ed411a4918 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 20 Mar 2024 21:28:10 +0300 Subject: [PATCH 31/42] Update Member query response for whitelist-immutable-flex --- .../whitelist-immutable-flex/src/contract.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/contracts/whitelists/whitelist-immutable-flex/src/contract.rs b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs index 05118f024..b2639576f 100644 --- a/contracts/whitelists/whitelist-immutable-flex/src/contract.rs +++ b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, StdR use cw2::set_contract_version; use crate::error::ContractError; -use crate::msg::{ConfigResponse, ExecuteMsg, InstantiateMsg, Member, QueryMsg}; +use crate::msg::{ConfigResponse, ExecuteMsg, InstantiateMsg, Member, MemberResponse, QueryMsg}; use cw_utils::nonpayable; use sg_std::Response; @@ -94,10 +94,12 @@ pub fn query_address_count(deps: Deps) -> StdResult { TOTAL_ADDRESS_COUNT.load(deps.storage) } -pub fn query_member(deps: Deps, address: String) -> StdResult { +pub fn query_member(deps: Deps, address: String) -> StdResult { let mint_count = WHITELIST.load(deps.storage, &address)?; - Ok(Member { - address, - mint_count, + Ok(MemberResponse { + member: Member { + address, + mint_count, + }, }) } From c733a78b7572b87b5d830c9bb1c7740778f6b9f5 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 20 Mar 2024 21:31:32 +0300 Subject: [PATCH 32/42] Add queries for registration, claim and airdrop count --- contracts/dydx-airdrop/src/msg.rs | 6 ++++++ contracts/dydx-airdrop/src/query.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index ce2829d56..409d56814 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -41,4 +41,10 @@ pub enum QueryMsg { AirdropEligible { eth_address: String }, #[returns(Addr)] GetMinter {}, + #[returns(bool)] + IsRegistered { eth_address: String }, + #[returns(bool)] + HasClaimed { eth_address: String }, + #[returns(u32)] + GetAirdropCount {}, } diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index d4bece88e..d40d0d82d 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -5,6 +5,7 @@ use cosmwasm_std::{Deps, DepsMut, StdResult}; use vending_minter::helpers::MinterContract; use whitelist_immutable_flex::helpers::WhitelistImmutableFlexContract; use whitelist_immutable_flex::msg::MemberResponse; +use crate::state::{AIRDROP_COUNT, HAS_CLAIMED, IS_ADDRESS_REGISTERED}; #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { @@ -13,6 +14,9 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { to_json_binary(&query_airdrop_is_eligible(deps, eth_address)?) } QueryMsg::GetMinter {} => to_json_binary(&query_minter(deps)?), + QueryMsg::IsRegistered { eth_address } => to_json_binary(&query_airdrop_is_registered(deps, eth_address)?), + QueryMsg::HasClaimed { eth_address } => to_json_binary(&query_airdrop_has_claimed(deps, eth_address)?), + QueryMsg::GetAirdropCount {} => to_json_binary(&query_airdrop_count(deps)?), } } @@ -32,6 +36,22 @@ pub fn query_airdrop_is_eligible(deps: Deps, eth_address: String) -> StdResult StdResult { + let airdrop_count = AIRDROP_COUNT.load(deps.storage)?; + Ok(airdrop_count) +} + +pub fn query_airdrop_is_registered(deps: Deps, eth_address: String) -> StdResult { + let is_registered = IS_ADDRESS_REGISTERED.may_load(deps.storage, ð_address)?; + Ok(is_registered.unwrap_or_default()) +} + +pub fn query_airdrop_has_claimed(deps: Deps, eth_address: String) -> StdResult { + let has_claimed = HAS_CLAIMED.may_load(deps.storage, ð_address)?; + Ok(has_claimed.unwrap_or_default()) +} + + pub fn query_collection_whitelist(deps: &DepsMut) -> Result { let config = CONFIG.load(deps.storage)?; let minter_addr = config.minter_address; From db8aa26252b8571c51d2e80113dcb4c13092795e Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 20 Mar 2024 22:31:03 +0300 Subject: [PATCH 33/42] Update schema --- .../dydx-airdrop/schema/dydx-airdrop.json | 72 +++++++++++++++++++ contracts/dydx-airdrop/schema/raw/query.json | 55 ++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/contracts/dydx-airdrop/schema/dydx-airdrop.json b/contracts/dydx-airdrop/schema/dydx-airdrop.json index fadf7cd61..28c5a7fe7 100644 --- a/contracts/dydx-airdrop/schema/dydx-airdrop.json +++ b/contracts/dydx-airdrop/schema/dydx-airdrop.json @@ -170,6 +170,61 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "is_registered" + ], + "properties": { + "is_registered": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "has_claimed" + ], + "properties": { + "has_claimed": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_airdrop_count" + ], + "properties": { + "get_airdrop_count": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false } ] }, @@ -181,11 +236,28 @@ "title": "Boolean", "type": "boolean" }, + "get_airdrop_count": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, "get_minter": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Addr", "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", "type": "string" + }, + "has_claimed": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" + }, + "is_registered": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Boolean", + "type": "boolean" } } } diff --git a/contracts/dydx-airdrop/schema/raw/query.json b/contracts/dydx-airdrop/schema/raw/query.json index c21aaf535..5fd2cdaf7 100644 --- a/contracts/dydx-airdrop/schema/raw/query.json +++ b/contracts/dydx-airdrop/schema/raw/query.json @@ -35,6 +35,61 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "is_registered" + ], + "properties": { + "is_registered": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "has_claimed" + ], + "properties": { + "has_claimed": { + "type": "object", + "required": [ + "eth_address" + ], + "properties": { + "eth_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_airdrop_count" + ], + "properties": { + "get_airdrop_count": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false } ] } From 28179ab15c496dd85caec04813dd6d19c6c3959d Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 20 Mar 2024 22:31:40 +0300 Subject: [PATCH 34/42] Update TS interface & types --- ts/src/DydxAirdrop.client.ts | 43 +++++++++++++++++++++++++++++++++++- ts/src/DydxAirdrop.types.ts | 11 +++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/ts/src/DydxAirdrop.client.ts b/ts/src/DydxAirdrop.client.ts index a9d3169a0..d16bd7867 100644 --- a/ts/src/DydxAirdrop.client.ts +++ b/ts/src/DydxAirdrop.client.ts @@ -6,7 +6,7 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { Coin, StdFee } from "@cosmjs/amino"; -import { InstantiateMsg, Member, ExecuteMsg, QueryMsg, Boolean, Addr } from "./DydxAirdrop.types"; +import { InstantiateMsg, Member, ExecuteMsg, QueryMsg, Boolean, Uint32, Addr } from "./DydxAirdrop.types"; export interface DydxAirdropReadOnlyInterface { contractAddress: string; airdropEligible: ({ @@ -15,6 +15,17 @@ export interface DydxAirdropReadOnlyInterface { ethAddress: string; }) => Promise; getMinter: () => Promise; + isRegistered: ({ + ethAddress + }: { + ethAddress: string; + }) => Promise; + hasClaimed: ({ + ethAddress + }: { + ethAddress: string; + }) => Promise; + getAirdropCount: () => Promise; } export class DydxAirdropQueryClient implements DydxAirdropReadOnlyInterface { client: CosmWasmClient; @@ -25,6 +36,9 @@ export class DydxAirdropQueryClient implements DydxAirdropReadOnlyInterface { this.contractAddress = contractAddress; this.airdropEligible = this.airdropEligible.bind(this); this.getMinter = this.getMinter.bind(this); + this.isRegistered = this.isRegistered.bind(this); + this.hasClaimed = this.hasClaimed.bind(this); + this.getAirdropCount = this.getAirdropCount.bind(this); } airdropEligible = async ({ @@ -43,6 +57,33 @@ export class DydxAirdropQueryClient implements DydxAirdropReadOnlyInterface { get_minter: {} }); }; + isRegistered = async ({ + ethAddress + }: { + ethAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + is_registered: { + eth_address: ethAddress + } + }); + }; + hasClaimed = async ({ + ethAddress + }: { + ethAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + has_claimed: { + eth_address: ethAddress + } + }); + }; + getAirdropCount = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_airdrop_count: {} + }); + }; } export interface DydxAirdropInterface extends DydxAirdropReadOnlyInterface { contractAddress: string; diff --git a/ts/src/DydxAirdrop.types.ts b/ts/src/DydxAirdrop.types.ts index 652656f2e..4b12a8057 100644 --- a/ts/src/DydxAirdrop.types.ts +++ b/ts/src/DydxAirdrop.types.ts @@ -36,6 +36,17 @@ export type QueryMsg = { }; } | { get_minter: {}; +} | { + is_registered: { + eth_address: string; + }; +} | { + has_claimed: { + eth_address: string; + }; +} | { + get_airdrop_count: {}; }; export type Boolean = boolean; +export type Uint32 = number; export type Addr = string; \ No newline at end of file From 2b8102d9b64b4a460e06fc87418d4ff07e8e47f6 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Fri, 22 Mar 2024 12:05:24 +0300 Subject: [PATCH 35/42] Add names/flat-rate-whitelist branch as a dependency --- Cargo.lock | 48 +++++++++++++++++++- Cargo.toml | 1 + contracts/dydx-airdrop/Cargo.toml | 1 + contracts/dydx-airdrop/src/build_messages.rs | 13 +++--- contracts/dydx-airdrop/src/query.rs | 13 ++++-- 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 272a7c0ea..7e42a6594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1471,6 +1471,7 @@ dependencies = [ "vending-minter", "whitelist-immutable-flex", "whitelist-updatable", + "whitelist-updatable-flatrate", ] [[package]] @@ -3831,6 +3832,18 @@ dependencies = [ "serde", ] +[[package]] +name = "sg-name-minter" +version = "2.1.0" +source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.16.0", + "schemars", + "serde", +] + [[package]] name = "sg-splits" version = "3.5.0" @@ -3923,6 +3936,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sg-whitelist-basic" +version = "2.1.0" +source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "sg-whitelist-flex" version = "3.5.0" @@ -5308,9 +5332,29 @@ dependencies = [ "cw2 0.16.0", "schemars", "serde", - "sg-name-minter", + "sg-name-minter 0.12.0", "sg-std 0.21.12", - "sg-whitelist-basic", + "sg-whitelist-basic 0.12.0", + "thiserror", +] + +[[package]] +name = "whitelist-updatable-flatrate" +version = "2.1.0" +source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers 0.16.0", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "schemars", + "semver", + "serde", + "sg-name-minter 2.1.0", + "sg-std 0.22.11", + "sg-whitelist-basic 2.1.0", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 5d2da85d2..50fe5084b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ open-edition-minter = { version = "3.5.0", path = "contracts/minters/open-editi whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable" } whitelist-immutable-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable-flex" } whitelist-updatable = "0.12.0" +whitelist-updatable-flatrate = {git = "https://github.com/public-awesome/names.git", branch = "flat-rate-whitelist"} sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } sg721-name = "1.2.5" ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index 55e52e8dd..230b45512 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -48,6 +48,7 @@ thiserror = { workspace = true } vending-minter = { workspace = true, features = ["library"] } whitelist-immutable-flex = { workspace = true, features = ["library"] } whitelist-updatable = { workspace = true, features = ["library"] } +whitelist-updatable-flatrate = { workspace = true, features = ["library"] } [dev-dependencies] async-std = "1.12.0" diff --git a/contracts/dydx-airdrop/src/build_messages.rs b/contracts/dydx-airdrop/src/build_messages.rs index a7712ddff..8158c2444 100644 --- a/contracts/dydx-airdrop/src/build_messages.rs +++ b/contracts/dydx-airdrop/src/build_messages.rs @@ -1,18 +1,17 @@ -use cosmwasm_std::{ - coins, to_json_binary, Addr, BankMsg, Deps, DepsMut, Env, MessageInfo, StdResult, WasmMsg, -}; -use sg_std::{CosmosMsg, Response, StargazeMsgWrapper, SubMsg, NATIVE_DENOM}; -use whitelist_updatable::msg::ExecuteMsg; -// TODO: Replace with whitelist_updatable_flatrate use crate::msg::InstantiateMsg; use crate::query::{query_collection_whitelist, query_mint_count}; use crate::state::{Config, CONFIG}; use crate::ContractError; +use cosmwasm_std::{ + coins, to_json_binary, Addr, BankMsg, Deps, DepsMut, Env, MessageInfo, StdResult, WasmMsg, +}; +use sg_std::{CosmosMsg, Response, StargazeMsgWrapper, SubMsg, NATIVE_DENOM}; use sg_whitelist_flex::helpers::interface::CollectionWhitelistContract; use sg_whitelist_flex::msg::AddMembersMsg; use sg_whitelist_flex::msg::{ExecuteMsg as CollectionWhitelistExecuteMsg, Member}; use whitelist_immutable_flex::msg::InstantiateMsg as WIFInstantiateMsg; -use whitelist_updatable::msg::ExecuteMsg::AddAddresses; +use whitelist_updatable_flatrate::msg::ExecuteMsg; +use whitelist_updatable_flatrate::msg::ExecuteMsg::AddAddresses; pub const IMMUTABLE_WHITELIST_LABEL: &str = "Whitelist Immutable Flex for Airdrop"; pub const INIT_WHITELIST_REPLY_ID: u64 = 1; diff --git a/contracts/dydx-airdrop/src/query.rs b/contracts/dydx-airdrop/src/query.rs index d40d0d82d..d8a4a064c 100644 --- a/contracts/dydx-airdrop/src/query.rs +++ b/contracts/dydx-airdrop/src/query.rs @@ -1,3 +1,4 @@ +use crate::state::{AIRDROP_COUNT, HAS_CLAIMED, IS_ADDRESS_REGISTERED}; use crate::{msg::QueryMsg, state::CONFIG, ContractError}; use cosmwasm_std::{entry_point, to_json_binary, Binary}; use cosmwasm_std::{Addr, Env}; @@ -5,7 +6,6 @@ use cosmwasm_std::{Deps, DepsMut, StdResult}; use vending_minter::helpers::MinterContract; use whitelist_immutable_flex::helpers::WhitelistImmutableFlexContract; use whitelist_immutable_flex::msg::MemberResponse; -use crate::state::{AIRDROP_COUNT, HAS_CLAIMED, IS_ADDRESS_REGISTERED}; #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { @@ -14,8 +14,12 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { to_json_binary(&query_airdrop_is_eligible(deps, eth_address)?) } QueryMsg::GetMinter {} => to_json_binary(&query_minter(deps)?), - QueryMsg::IsRegistered { eth_address } => to_json_binary(&query_airdrop_is_registered(deps, eth_address)?), - QueryMsg::HasClaimed { eth_address } => to_json_binary(&query_airdrop_has_claimed(deps, eth_address)?), + QueryMsg::IsRegistered { eth_address } => { + to_json_binary(&query_airdrop_is_registered(deps, eth_address)?) + } + QueryMsg::HasClaimed { eth_address } => { + to_json_binary(&query_airdrop_has_claimed(deps, eth_address)?) + } QueryMsg::GetAirdropCount {} => to_json_binary(&query_airdrop_count(deps)?), } } @@ -42,7 +46,7 @@ pub fn query_airdrop_count(deps: Deps) -> StdResult { } pub fn query_airdrop_is_registered(deps: Deps, eth_address: String) -> StdResult { - let is_registered = IS_ADDRESS_REGISTERED.may_load(deps.storage, ð_address)?; + let is_registered = IS_ADDRESS_REGISTERED.may_load(deps.storage, ð_address)?; Ok(is_registered.unwrap_or_default()) } @@ -51,7 +55,6 @@ pub fn query_airdrop_has_claimed(deps: Deps, eth_address: String) -> StdResult Result { let config = CONFIG.load(deps.storage)?; let minter_addr = config.minter_address; From e8a020d8d950e302105714aba9f788008d7ac348 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 27 Mar 2024 12:37:41 +0300 Subject: [PATCH 36/42] Update dependency for whitelist-updatable-flatrate --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e42a6594..144566d45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3835,7 +3835,7 @@ dependencies = [ [[package]] name = "sg-name-minter" version = "2.1.0" -source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +source = "git+https://github.com/public-awesome/names.git?branch=dYdX-airdrop#eeb9b9002d0a8da979103f95d8937cef31ba5121" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -3939,7 +3939,7 @@ dependencies = [ [[package]] name = "sg-whitelist-basic" version = "2.1.0" -source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +source = "git+https://github.com/public-awesome/names.git?branch=dYdX-airdrop#eeb9b9002d0a8da979103f95d8937cef31ba5121" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -5341,7 +5341,7 @@ dependencies = [ [[package]] name = "whitelist-updatable-flatrate" version = "2.1.0" -source = "git+https://github.com/public-awesome/names.git?branch=flat-rate-whitelist#33fec3cd6714ec279e6f7ff7b31b691385ac04ee" +source = "git+https://github.com/public-awesome/names.git?branch=dYdX-airdrop#eeb9b9002d0a8da979103f95d8937cef31ba5121" dependencies = [ "cosmwasm-schema", "cosmwasm-std", diff --git a/Cargo.toml b/Cargo.toml index 50fe5084b..c5eb7b28f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ open-edition-minter = { version = "3.5.0", path = "contracts/minters/open-editi whitelist-immutable = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable" } whitelist-immutable-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-immutable-flex" } whitelist-updatable = "0.12.0" -whitelist-updatable-flatrate = {git = "https://github.com/public-awesome/names.git", branch = "flat-rate-whitelist"} +whitelist-updatable-flatrate = {git = "https://github.com/public-awesome/names.git", branch = "dYdX-airdrop"} sg-whitelist-flex = { version = "3.5.0", path = "contracts/whitelists/whitelist-flex" } sg721-name = "1.2.5" ethereum-verify = { version = "3.5.0", path = "packages/ethereum-verify" } From 613978f62e71c7727c99df455dc2e47f51074c28 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Mon, 25 Mar 2024 22:45:21 -0600 Subject: [PATCH 37/42] eth-verify recovery param --- packages/ethereum-verify/src/decode.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ethereum-verify/src/decode.rs b/packages/ethereum-verify/src/decode.rs index 0628aac82..8b823da72 100644 --- a/packages/ethereum-verify/src/decode.rs +++ b/packages/ethereum-verify/src/decode.rs @@ -10,6 +10,7 @@ use sha3::{Digest, Keccak256}; /// [EIP-155]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md pub fn get_recovery_param(v: u8) -> StdResult { match v { + 0 | 1 => Ok(v), 27 => Ok(0), 28 => Ok(1), _ => Err(StdError::generic_err("Values of v other than 27 and 28 not supported. Replay protection (EIP-155) cannot be used here.")) From 06bfc80001c093cb31ae2fa71b2ceb65bcf2bc47 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Wed, 27 Mar 2024 13:17:05 -0600 Subject: [PATCH 38/42] whitelist updates --- contracts/whitelists/whitelist-flex/src/contract.rs | 9 ++++----- .../whitelists/whitelist-immutable-flex/src/contract.rs | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/whitelists/whitelist-flex/src/contract.rs b/contracts/whitelists/whitelist-flex/src/contract.rs index dc6e56d84..a415d6e03 100644 --- a/contracts/whitelists/whitelist-flex/src/contract.rs +++ b/contracts/whitelists/whitelist-flex/src/contract.rs @@ -26,7 +26,7 @@ const CONTRACT_NAME: &str = "crates.io:sg-whitelist-flex"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); // contract governance params -pub const MAX_MEMBERS: u32 = 5000; +pub const MAX_MEMBERS: u32 = 25_000; pub const PRICE_PER_1000_MEMBERS: u128 = 100_000_000; pub const MIN_MINT_PRICE: u128 = 0; @@ -233,11 +233,10 @@ pub fn execute_add_members( }); } let addr = deps.api.addr_validate(&add.address)?; - if WHITELIST.has(deps.storage, addr.clone()) { - return Err(ContractError::DuplicateMember(addr.to_string())); + if !WHITELIST.has(deps.storage, addr.clone()) { + WHITELIST.save(deps.storage, addr, &add.mint_count)?; + config.num_members += 1; } - WHITELIST.save(deps.storage, addr, &add.mint_count)?; - config.num_members += 1; } CONFIG.save(deps.storage, &config)?; diff --git a/contracts/whitelists/whitelist-immutable-flex/src/contract.rs b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs index b2639576f..f2fca7238 100644 --- a/contracts/whitelists/whitelist-immutable-flex/src/contract.rs +++ b/contracts/whitelists/whitelist-immutable-flex/src/contract.rs @@ -42,7 +42,8 @@ pub fn instantiate( fn update_whitelist(deps: &mut DepsMut, msg: InstantiateMsg) -> Result { let mut count = 0u64; for member in msg.members.into_iter() { - WHITELIST.save(deps.storage, &member.address, &member.mint_count)?; + let address_lower = member.address.clone().to_ascii_lowercase(); + WHITELIST.save(deps.storage, &address_lower, &member.mint_count)?; count += 1; } Ok(count) From fcce9e3bcfcede86dabb72b75bd0e5da29d97d49 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 24 Apr 2024 17:16:10 +0300 Subject: [PATCH 39/42] Add withdraw_remaining() for dYdX-airdrop contract --- contracts/dydx-airdrop/src/contract.rs | 70 +++++++++++++++++++++++--- contracts/dydx-airdrop/src/error.rs | 5 +- contracts/dydx-airdrop/src/msg.rs | 6 ++- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index 2fa7d4d95..cf16336dc 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -1,14 +1,14 @@ use crate::claim_airdrop::claim_airdrop; -#[cfg(not(feature = "library"))] +// #[cfg(not(feature = "library"))] use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg}; use crate::state::{AIRDROP_COUNT, CONFIG}; -use cosmwasm_std::entry_point; +use cosmwasm_std::{attr, ensure, entry_point, BankMsg, Coin, CosmosMsg, Uint128}; use cosmwasm_std::{DepsMut, Env, MessageInfo}; use cw2::set_contract_version; use sg1::fair_burn; -use sg_std::Response; +use sg_std::{Response, NATIVE_DENOM}; use crate::build_messages::{state_config, whitelist_instantiate}; use crate::register::register; @@ -43,7 +43,7 @@ pub fn instantiate( #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( deps: DepsMut, - _env: Env, + env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { @@ -51,10 +51,68 @@ pub fn execute( ExecuteMsg::Register { eth_address, eth_sig, - } => register(deps, info, _env, eth_address, eth_sig), + } => register(deps, info, env, eth_address, eth_sig), ExecuteMsg::ClaimAirdrop { eth_address, eth_sig, - } => claim_airdrop(deps, info, _env, eth_address, eth_sig), + } => claim_airdrop(deps, info, env, eth_address, eth_sig), + ExecuteMsg::WithdrawRemaining { recipient, amount } => { + withdraw_remaining(deps, info, env, recipient, amount) + } } } + +pub fn withdraw_remaining( + deps: DepsMut, + info: MessageInfo, + env: Env, + recipient: String, + amount: Option, +) -> Result { + let contract_info = deps + .querier + .query_wasm_contract_info(env.contract.address.clone())?; + ensure!( + contract_info.admin.is_some() && contract_info.admin.unwrap() == info.sender, + ContractError::Unauthorized { + sender: info.sender + } + ); + + let total_amount = deps + .querier + .query_balance(env.contract.address.clone(), NATIVE_DENOM)? + .amount; + + let recipient_addr = deps.api.addr_validate(&recipient)?; + + let amount_to_withdraw = match amount { + Some(amount) => { + if amount > total_amount { + return Err(ContractError::InsufficientFunds { + balance: total_amount, + amount, + }); + } + amount + } + None => total_amount, + }; + + let msg = BankMsg::Send { + to_address: recipient.into(), + amount: vec![Coin { + denom: NATIVE_DENOM.to_string(), + amount: amount_to_withdraw, + }], + }; + + let res = Response::new() + .add_message(CosmosMsg::Bank(msg)) + .add_attributes(vec![ + attr("action", "withdraw_remaining"), + attr("amount", amount_to_withdraw), + attr("recipient", recipient_addr.to_string()), + ]); + Ok(res) +} diff --git a/contracts/dydx-airdrop/src/error.rs b/contracts/dydx-airdrop/src/error.rs index 5f79ad74e..39f42fb4a 100644 --- a/contracts/dydx-airdrop/src/error.rs +++ b/contracts/dydx-airdrop/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, StdError}; +use cosmwasm_std::{Addr, StdError, Uint128}; use cw_utils::{self, PaymentError}; use thiserror::Error; @@ -75,4 +75,7 @@ pub enum ContractError { #[error("Address {address} should be converted to lowercase")] EthAddressShouldBeLower { address: String }, + + #[error("Insufficient Funds: Contract balance: {balance} does not cover the required amount: {amount}")] + InsufficientFunds { balance: Uint128, amount: Uint128 }, } diff --git a/contracts/dydx-airdrop/src/msg.rs b/contracts/dydx-airdrop/src/msg.rs index 409d56814..66c2887a4 100644 --- a/contracts/dydx-airdrop/src/msg.rs +++ b/contracts/dydx-airdrop/src/msg.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Addr; +use cosmwasm_std::{Addr, Uint128}; use whitelist_immutable_flex::msg::Member; #[cw_serde] @@ -32,6 +32,10 @@ pub enum ExecuteMsg { eth_address: String, eth_sig: String, }, + WithdrawRemaining { + recipient: String, + amount: Option, + }, } #[cw_serde] From 5e7d9be2f9d9d31cd9e0f08d9fec996f1e303386 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 24 Apr 2024 17:19:23 +0300 Subject: [PATCH 40/42] Address clippy issues --- contracts/dydx-airdrop/src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index cf16336dc..b7d30cc19 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -100,7 +100,7 @@ pub fn withdraw_remaining( }; let msg = BankMsg::Send { - to_address: recipient.into(), + to_address: recipient_addr.to_string(), amount: vec![Coin { denom: NATIVE_DENOM.to_string(), amount: amount_to_withdraw, From 3a5ba09fe928d24b48c38c848112c0149ec5a070 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 24 Apr 2024 17:26:12 +0300 Subject: [PATCH 41/42] Add migration code --- Cargo.lock | 1 + contracts/dydx-airdrop/Cargo.toml | 1 + contracts/dydx-airdrop/src/contract.rs | 37 +++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 144566d45..bb3c5438a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1456,6 +1456,7 @@ dependencies = [ "rlp", "rust_decimal", "schemars", + "semver", "serde", "sg-multi-test", "sg-std 3.2.0", diff --git a/contracts/dydx-airdrop/Cargo.toml b/contracts/dydx-airdrop/Cargo.toml index 230b45512..892ea22a5 100644 --- a/contracts/dydx-airdrop/Cargo.toml +++ b/contracts/dydx-airdrop/Cargo.toml @@ -43,6 +43,7 @@ sha2 = { workspace = true } sha3 = "0.10" schemars = { workspace = true } serde = { workspace = true } +semver = { workspace = true } sg-std = { workspace = true } thiserror = { workspace = true } vending-minter = { workspace = true, features = ["library"] } diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index b7d30cc19..0980423bb 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -4,9 +4,12 @@ use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg}; use crate::state::{AIRDROP_COUNT, CONFIG}; -use cosmwasm_std::{attr, ensure, entry_point, BankMsg, Coin, CosmosMsg, Uint128}; +use cosmwasm_std::{ + attr, ensure, entry_point, BankMsg, Coin, CosmosMsg, Empty, Event, StdError, Uint128, +}; use cosmwasm_std::{DepsMut, Env, MessageInfo}; use cw2::set_contract_version; +use semver::Version; use sg1::fair_burn; use sg_std::{Response, NATIVE_DENOM}; @@ -116,3 +119,35 @@ pub fn withdraw_remaining( ]); Ok(res) } + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result { + let current_version = cw2::get_contract_version(deps.storage)?; + if current_version.contract != CONTRACT_NAME { + return Err(StdError::generic_err("Cannot upgrade to a different contract").into()); + } + let version: Version = current_version + .version + .parse() + .map_err(|_| StdError::generic_err("Invalid contract version"))?; + let new_version: Version = CONTRACT_VERSION + .parse() + .map_err(|_| StdError::generic_err("Invalid contract version"))?; + + if version > new_version { + return Err(StdError::generic_err("Cannot upgrade to a previous contract version").into()); + } + // if same version return + if version == new_version { + return Ok(Response::new()); + } + + // set new contract version + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + let event = Event::new("migrate") + .add_attribute("from_name", current_version.contract) + .add_attribute("from_version", current_version.version) + .add_attribute("to_name", CONTRACT_NAME) + .add_attribute("to_version", CONTRACT_VERSION); + Ok(Response::new().add_event(event)) +} From 19e29cb8f31b8cd002ad331e72d3dbaf1dc2a5b5 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Wed, 24 Apr 2024 19:10:42 +0300 Subject: [PATCH 42/42] Avoid redefining ContractError when feature = library --- contracts/dydx-airdrop/src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/dydx-airdrop/src/contract.rs b/contracts/dydx-airdrop/src/contract.rs index 0980423bb..853ac791b 100644 --- a/contracts/dydx-airdrop/src/contract.rs +++ b/contracts/dydx-airdrop/src/contract.rs @@ -1,5 +1,5 @@ use crate::claim_airdrop::claim_airdrop; -// #[cfg(not(feature = "library"))] +#[cfg(not(feature = "library"))] use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg}; use crate::state::{AIRDROP_COUNT, CONFIG};