diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 8662bf3e9..69893fc6e 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -28,11 +28,11 @@ jobs: docker-images: true swap-storage: true - - name: Install latest nightly toolchain + - name: Install nightly-2025-01-09 toolchain uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2023-02-02 + toolchain: nightly-2025-01-09 target: wasm32-unknown-unknown override: true diff --git a/.github/workflows/test_tube.yml b/.github/workflows/test_tube.yml index 001908f12..786a76f7e 100644 --- a/.github/workflows/test_tube.yml +++ b/.github/workflows/test_tube.yml @@ -28,11 +28,11 @@ jobs: docker-images: true swap-storage: true - - name: Install latest nightly toolchain + - name: Install nightly-2025-01-09 toolchain uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly-2024-01-08 + toolchain: nightly-2025-01-09 target: wasm32-unknown-unknown override: true diff --git a/.gitignore b/.gitignore index 84e31c7b2..e9c08205a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,5 @@ ci/configs/cosm-orc/local.yaml contracts/**/Cargo.lock packages/**/Cargo.lock debug/**/Cargo.lock -ci/**/Cargo.lock \ No newline at end of file +ci/**/Cargo.lock +.aider* diff --git a/Cargo.toml b/Cargo.toml index 7e32dbdfa..089cc485b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,9 +42,9 @@ cosm-orc = { version = "4.0" } cosm-tome = "0.2" cosmos-sdk-proto = "0.19" cosmwasm-schema = { version = "1.5.4" } -cosmwasm-std = { version = "1.5.4", features = ["ibc3", "cosmwasm_1_1"] } +cosmwasm-std = { version = "1.5.4", features = ["ibc3", "cosmwasm_1_2"] } cw-controllers = "1.1" -cw-multi-test = { version = "0.20.1", features = ["cosmwasm_1_1"] } +cw-multi-test = { version = "0.20.1", features = ["cosmwasm_1_2"] } cw-storage-plus = { version = "1.1" } cw-utils = "1.0" cw2 = "1.1" diff --git a/ci/bootstrap-env/src/main.rs b/ci/bootstrap-env/src/main.rs index 50ca7c71d..970167f95 100644 --- a/ci/bootstrap-env/src/main.rs +++ b/ci/bootstrap-env/src/main.rs @@ -59,6 +59,7 @@ fn main() -> Result<()> { msg: to_json_binary(&dao_voting_cw20_staked::msg::InstantiateMsg { token_info: dao_voting_cw20_staked::msg::TokenInfo::New { code_id: orc.contract_map.code_id("cw20_base")?, + salt: None, label: "DAO DAO Gov token".to_string(), name: "DAO".to_string(), symbol: "DAO".to_string(), @@ -69,14 +70,16 @@ fn main() -> Result<()> { }], marketing: None, staking_code_id: orc.contract_map.code_id("cw20_stake")?, + staking_salt: None, unstaking_duration: Some(cw_utils::Duration::Time(1209600)), initial_dao_balance: None, }, active_threshold: None, })?, - funds: vec![], + funds: None, admin: Some(Admin::CoreModule {}), label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: orc.contract_map.code_id("dao_proposal_single")?, @@ -109,8 +112,9 @@ fn main() -> Result<()> { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Pre-Propose Module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -118,8 +122,9 @@ fn main() -> Result<()> { delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/ci/integration-tests/src/helpers/helper.rs b/ci/integration-tests/src/helpers/helper.rs index 9ba02057f..8cfe4478e 100644 --- a/ci/integration-tests/src/helpers/helper.rs +++ b/ci/integration-tests/src/helpers/helper.rs @@ -42,6 +42,7 @@ pub fn create_dao( msg: to_json_binary(&dao_voting_cw20_staked::msg::InstantiateMsg { token_info: dao_voting_cw20_staked::msg::TokenInfo::New { code_id: chain.orc.contract_map.code_id("cw20_base")?, + salt: None, label: "DAO DAO Gov token".to_string(), name: "DAO".to_string(), symbol: "DAO".to_string(), @@ -52,6 +53,7 @@ pub fn create_dao( }], marketing: None, staking_code_id: chain.orc.contract_map.code_id("cw20_stake")?, + staking_salt: None, unstaking_duration: Some(Duration::Time(1209600)), initial_dao_balance: None, }, @@ -59,7 +61,8 @@ pub fn create_dao( })?, admin: Some(Admin::CoreModule {}), label: "DAO DAO Voting Module".to_string(), - funds: vec![], + funds: None, + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: chain.orc.contract_map.code_id("dao_proposal_single")?, @@ -93,16 +96,18 @@ pub fn create_dao( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Pre-Propose Module".to_string(), + salt: None, }, }, veto: None, delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/dao-dao-core/schema/dao-dao-core.json b/contracts/dao-dao-core/schema/dao-dao-core.json index c4488c74d..17a30945f 100644 --- a/contracts/dao-dao-core/schema/dao-dao-core.json +++ b/contracts/dao-dao-core/schema/dao-dao-core.json @@ -621,7 +621,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -645,7 +644,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -661,6 +663,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -2040,7 +2053,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -2064,7 +2076,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -2080,6 +2095,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -3083,7 +3109,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -3107,7 +3132,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -3123,6 +3151,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/dao-dao-core/src/contract.rs b/contracts/dao-dao-core/src/contract.rs index 7de8a8000..8b2dd1eb8 100644 --- a/contracts/dao-dao-core/src/contract.rs +++ b/contracts/dao-dao-core/src/contract.rs @@ -951,7 +951,8 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> Result>(); governance_modules.push(ModuleInstantiateInfo { code_id: cw20_id, msg: to_json_binary("bad").unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "I have a bad instantiate message".to_string(), + salt: None, }); governance_modules.push(ModuleInstantiateInfo { code_id: cw20_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "Everybody knowing that goodness is good makes wickedness." .to_string(), + salt: None, }); let instantiate = InstantiateMsg { @@ -179,8 +184,9 @@ makes wickedness." code_id: cw20_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: governance_modules, initial_items: None, @@ -211,15 +217,17 @@ fn test_update_config() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -311,15 +319,17 @@ fn test_swap_governance(swaps: Vec<(u32, u32)>) { code_id: propmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: propmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -383,8 +393,9 @@ fn test_swap_governance(swaps: Vec<(u32, u32)>) { code_id: propmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: format!("governance module {n}"), + salt: None, }) .collect(); @@ -491,15 +502,17 @@ fn test_removed_modules_can_not_execute() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -535,8 +548,9 @@ fn test_removed_modules_can_not_execute() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "new governance module".to_string(), + salt: None, }]; let to_disable = vec![start_module.address.to_string()]; @@ -568,8 +582,9 @@ fn test_removed_modules_can_not_execute() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "new governance module".to_string(), + salt: None, }]; let to_disable = vec![new_proposal_module.address.to_string()]; @@ -655,15 +670,17 @@ fn test_module_already_disabled() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -713,8 +730,9 @@ fn test_module_already_disabled() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], to_disable, }) @@ -758,15 +776,17 @@ fn test_swap_voting_module() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -813,8 +833,9 @@ fn test_swap_voting_module() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, }) .unwrap(), @@ -863,15 +884,17 @@ fn test_permissions() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, automatically_add_cw20s: true, @@ -898,8 +921,9 @@ fn test_permissions() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, }, ); @@ -951,6 +975,7 @@ fn do_standard_instantiate(auto_add: bool, admin: Option) -> (Addr, App) amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -966,15 +991,17 @@ fn do_standard_instantiate(auto_add: bool, admin: Option) -> (Addr, App) code_id: voting_id, msg: to_json_binary(&voting_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -1669,6 +1696,7 @@ fn test_list_items() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -1684,15 +1712,17 @@ fn test_list_items() { code_id: voting_id, msg: to_json_binary(&voting_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -1789,6 +1819,7 @@ fn test_instantiate_with_items() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -1819,15 +1850,17 @@ fn test_instantiate_with_items() { code_id: voting_id, msg: to_json_binary(&voting_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: Some(initial_items.clone()), initial_actions: None, @@ -2633,6 +2666,7 @@ fn test_migrate_from_compatible() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -2649,15 +2683,17 @@ fn test_migrate_from_compatible() { code_id: voting_id, msg: to_json_binary(&voting_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -2723,6 +2759,7 @@ fn test_migrate_from_beta() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -2935,30 +2972,34 @@ fn test_module_prefixes() { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "proposal module 1".to_string(), + salt: None, }, ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "proposal module 2".to_string(), + salt: None, }, ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "proposal module 2".to_string(), + salt: None, }, ], initial_items: None, @@ -3192,6 +3233,7 @@ fn test_initial_actions() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }; @@ -3207,15 +3249,17 @@ fn test_initial_actions() { code_id: voting_id, msg: to_json_binary(&voting_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: govmod_id, msg: to_json_binary(&govmod_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "governance module".to_string(), + salt: None, }], initial_items: None, // Send 50 tokens to CREATOR on instantiation from the DAO's account. diff --git a/contracts/delegation/dao-vote-delegation/Cargo.toml b/contracts/delegation/dao-vote-delegation/Cargo.toml index 052736422..db53b4070 100644 --- a/contracts/delegation/dao-vote-delegation/Cargo.toml +++ b/contracts/delegation/dao-vote-delegation/Cargo.toml @@ -45,6 +45,6 @@ dao-voting-cw4 = { workspace = true, features = ["library"] } dao-voting-token-staked = { workspace = true, features = ["library"] } dao-voting-cw721-staked = { workspace = true, features = ["library"] } dao-testing = { workspace = true } -dao-proposal-sudo = { workspace = true } -dao-proposal-single = { workspace = true } -dao-proposal-multiple = { workspace = true } +dao-proposal-sudo = { workspace = true, features = ["library"] } +dao-proposal-single = { workspace = true, features = ["library"] } +dao-proposal-multiple = { workspace = true, features = ["library"] } diff --git a/contracts/delegation/dao-vote-delegation/src/testing/tests.rs b/contracts/delegation/dao-vote-delegation/src/testing/tests.rs index 7d819972b..9449f6baa 100644 --- a/contracts/delegation/dao-vote-delegation/src/testing/tests.rs +++ b/contracts/delegation/dao-vote-delegation/src/testing/tests.rs @@ -559,7 +559,8 @@ fn test_update_hook_callers() { .unwrap(), admin: None, label: "sudo".to_string(), - funds: vec![], + funds: None, + salt: None, }], to_disable: vec![], }, diff --git a/contracts/distribution/cw-fund-distributor/schema/cw-fund-distributor.json b/contracts/distribution/cw-fund-distributor/schema/cw-fund-distributor.json index ae3e73162..c3b0d1cd9 100644 --- a/contracts/distribution/cw-fund-distributor/schema/cw-fund-distributor.json +++ b/contracts/distribution/cw-fund-distributor/schema/cw-fund-distributor.json @@ -273,6 +273,17 @@ "format": "uint64", "minimum": 0.0 }, + "staking_salt": { + "description": "Optionally instantiate the staking contract via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "unstaking_duration": { "description": "See corresponding field in cw20-stake's instantiation. This will be used when instantiating the new staking contract.", "anyOf": [ @@ -387,11 +398,33 @@ "name": { "type": "string" }, + "salt": { + "description": "Optionally instantiate the token via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "staking_code_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, + "staking_salt": { + "description": "Optionally instantiate the staking contract via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "symbol": { "type": "string" }, diff --git a/contracts/distribution/cw-fund-distributor/src/testing/adversarial_tests.rs b/contracts/distribution/cw-fund-distributor/src/testing/adversarial_tests.rs index 4f3c2591e..394ff7192 100644 --- a/contracts/distribution/cw-fund-distributor/src/testing/adversarial_tests.rs +++ b/contracts/distribution/cw-fund-distributor/src/testing/adversarial_tests.rs @@ -63,6 +63,8 @@ fn setup_test(initial_balances: Vec) -> BaseTest { staking_code_id: stake_cw20_id, unstaking_duration: None, initial_dao_balance: None, + salt: None, + staking_salt: None, }, }, &[], diff --git a/contracts/distribution/cw-fund-distributor/src/testing/tests.rs b/contracts/distribution/cw-fund-distributor/src/testing/tests.rs index 504fc7157..757c26b6f 100644 --- a/contracts/distribution/cw-fund-distributor/src/testing/tests.rs +++ b/contracts/distribution/cw-fund-distributor/src/testing/tests.rs @@ -50,6 +50,8 @@ fn setup_test(initial_balances: Vec) -> BaseTest { staking_code_id: stake_cw20_id, unstaking_duration: None, initial_dao_balance: None, + salt: None, + staking_salt: None, }, }, &[], @@ -259,6 +261,8 @@ fn test_instantiate_fails_zero_voting_power() { staking_code_id: stake_cw20_id, unstaking_duration: None, initial_dao_balance: None, + salt: None, + staking_salt: None, }, }, &[], diff --git a/contracts/external/btsg-ft-factory/src/testing/tests.rs b/contracts/external/btsg-ft-factory/src/testing/tests.rs index f14bf3fc6..620cbbbfe 100644 --- a/contracts/external/btsg-ft-factory/src/testing/tests.rs +++ b/contracts/external/btsg-ft-factory/src/testing/tests.rs @@ -68,8 +68,9 @@ fn test_issue_fantoken() -> anyhow::Result<()> { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -87,8 +88,9 @@ fn test_issue_fantoken() -> anyhow::Result<()> { delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -172,8 +174,9 @@ fn test_initial_fantoken_balances() -> anyhow::Result<()> { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -191,8 +194,9 @@ fn test_initial_fantoken_balances() -> anyhow::Result<()> { delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -281,8 +285,9 @@ fn test_fantoken_minter_and_authority_set_to_dao() -> anyhow::Result<()> { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -300,8 +305,9 @@ fn test_fantoken_minter_and_authority_set_to_dao() -> anyhow::Result<()> { delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -440,8 +446,9 @@ fn test_fantoken_can_be_staked() -> anyhow::Result<()> { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -459,8 +466,9 @@ fn test_fantoken_can_be_staked() -> anyhow::Result<()> { delegation_module: None, })?, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/external/cw-admin-factory/src/integration_tests.rs b/contracts/external/cw-admin-factory/src/integration_tests.rs index 4c6325b8d..44c2dca91 100644 --- a/contracts/external/cw-admin-factory/src/integration_tests.rs +++ b/contracts/external/cw-admin-factory/src/integration_tests.rs @@ -74,7 +74,7 @@ fn test_set_self_admin_instantiate2() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Voting Module".to_string(), }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { @@ -95,7 +95,7 @@ fn test_set_self_admin_instantiate2() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), }], initial_items: None, diff --git a/contracts/external/cw-admin-factory/src/tests.rs b/contracts/external/cw-admin-factory/src/tests.rs index 8e8042f15..6a75ea672 100644 --- a/contracts/external/cw-admin-factory/src/tests.rs +++ b/contracts/external/cw-admin-factory/src/tests.rs @@ -60,23 +60,26 @@ pub fn test_set_self_admin() { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ ModuleInstantiateInfo { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "prop module".to_string(), + salt: None, }, ModuleInstantiateInfo { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "prop module 2".to_string(), + salt: None, }, ], initial_items: None, @@ -155,23 +158,26 @@ pub fn test_authorized_set_self_admin() { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ ModuleInstantiateInfo { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "prop module".to_string(), + salt: None, }, ModuleInstantiateInfo { code_id: cw20_code_id, msg: to_json_binary(&cw20_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "prop module 2".to_string(), + salt: None, }, ], initial_items: None, diff --git a/contracts/external/dao-migrator/schema/dao-migrator.json b/contracts/external/dao-migrator/schema/dao-migrator.json index 9f3087d74..39ee898e6 100644 --- a/contracts/external/dao-migrator/schema/dao-migrator.json +++ b/contracts/external/dao-migrator/schema/dao-migrator.json @@ -163,7 +163,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -187,7 +186,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -203,6 +205,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -557,7 +570,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -581,7 +593,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -597,6 +612,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/external/dao-migrator/src/testing/setup.rs b/contracts/external/dao-migrator/src/testing/setup.rs index 4b039a502..3dd70332b 100644 --- a/contracts/external/dao-migrator/src/testing/setup.rs +++ b/contracts/external/dao-migrator/src/testing/setup.rs @@ -315,8 +315,9 @@ pub fn execute_migration( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "migrator".to_string(), + salt: None, }], to_disable: vec![], }) diff --git a/contracts/pre-propose/dao-pre-propose-approval-multiple/src/tests.rs b/contracts/pre-propose/dao-pre-propose-approval-multiple/src/tests.rs index 85aa629d9..af085c4e6 100644 --- a/contracts/pre-propose/dao-pre-propose-approval-multiple/src/tests.rs +++ b/contracts/pre-propose/dao-pre-propose-approval-multiple/src/tests.rs @@ -87,8 +87,9 @@ fn get_default_proposal_module_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1789,8 +1790,9 @@ fn test_instantiate_with_zero_native_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1859,8 +1861,9 @@ fn test_instantiate_with_zero_cw20_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/pre-propose/dao-pre-propose-approval-single/src/tests.rs b/contracts/pre-propose/dao-pre-propose-approval-single/src/tests.rs index c1f581721..01d17d311 100644 --- a/contracts/pre-propose/dao-pre-propose-approval-single/src/tests.rs +++ b/contracts/pre-propose/dao-pre-propose-approval-single/src/tests.rs @@ -77,8 +77,9 @@ fn get_default_proposal_module_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1694,8 +1695,9 @@ fn test_instantiate_with_zero_native_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1764,8 +1766,9 @@ fn test_instantiate_with_zero_cw20_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/pre-propose/dao-pre-propose-approver/src/tests/multiple.rs b/contracts/pre-propose/dao-pre-propose-approver/src/tests/multiple.rs index fcce347ba..6fd83ea53 100644 --- a/contracts/pre-propose/dao-pre-propose-approver/src/tests/multiple.rs +++ b/contracts/pre-propose/dao-pre-propose-approver/src/tests/multiple.rs @@ -127,8 +127,9 @@ fn get_proposal_module_approval_multiple_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module, needs supervision".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -161,8 +162,9 @@ fn get_proposal_module_approver_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "approver module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/pre-propose/dao-pre-propose-approver/src/tests/single.rs b/contracts/pre-propose/dao-pre-propose-approver/src/tests/single.rs index 9a1b24386..f1f3de6c3 100644 --- a/contracts/pre-propose/dao-pre-propose-approver/src/tests/single.rs +++ b/contracts/pre-propose/dao-pre-propose-approver/src/tests/single.rs @@ -77,8 +77,9 @@ fn get_proposal_module_approval_single_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module, needs supervision".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -111,8 +112,9 @@ fn get_proposal_module_approver_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "approver module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/pre-propose/dao-pre-propose-multiple/src/tests.rs b/contracts/pre-propose/dao-pre-propose-multiple/src/tests.rs index b08ddbad1..8e4988c27 100644 --- a/contracts/pre-propose/dao-pre-propose-multiple/src/tests.rs +++ b/contracts/pre-propose/dao-pre-propose-multiple/src/tests.rs @@ -79,8 +79,9 @@ fn get_default_proposal_module_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1362,8 +1363,9 @@ fn test_instantiate_with_zero_native_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1430,8 +1432,9 @@ fn test_instantiate_with_zero_cw20_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/pre-propose/dao-pre-propose-single/src/tests.rs b/contracts/pre-propose/dao-pre-propose-single/src/tests.rs index 833da2168..184b21e98 100644 --- a/contracts/pre-propose/dao-pre-propose-single/src/tests.rs +++ b/contracts/pre-propose/dao-pre-propose-single/src/tests.rs @@ -75,8 +75,9 @@ fn get_default_proposal_module_instantiate( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1272,8 +1273,9 @@ fn test_instantiate_with_zero_native_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, @@ -1340,8 +1342,9 @@ fn test_instantiate_with_zero_cw20_deposit() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "baby's first pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: false, diff --git a/contracts/proposal/dao-proposal-condorcet/src/testing/suite.rs b/contracts/proposal/dao-proposal-condorcet/src/testing/suite.rs index a8157a441..4d78e12b8 100644 --- a/contracts/proposal/dao-proposal-condorcet/src/testing/suite.rs +++ b/contracts/proposal/dao-proposal-condorcet/src/testing/suite.rs @@ -92,20 +92,23 @@ impl SuiteBuilder { msg: to_json_binary(&dao_voting_cw4::msg::InstantiateMsg { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, + cw4_group_salt: None, initial_members, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: condorcet_id, msg: to_json_binary(&self.instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "condorcet module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/proposal/dao-proposal-multiple/schema/dao-proposal-multiple.json b/contracts/proposal/dao-proposal-multiple/schema/dao-proposal-multiple.json index 63de23882..987b39421 100644 --- a/contracts/proposal/dao-proposal-multiple/schema/dao-proposal-multiple.json +++ b/contracts/proposal/dao-proposal-multiple/schema/dao-proposal-multiple.json @@ -186,7 +186,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -210,7 +209,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -226,6 +228,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -1283,7 +1296,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -1307,7 +1319,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -1323,6 +1338,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -2383,7 +2409,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -2407,7 +2432,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -2423,6 +2451,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/proposal/dao-proposal-multiple/src/testing/instantiate.rs b/contracts/proposal/dao-proposal-multiple/src/testing/instantiate.rs index e38e9a8a4..622d68cee 100644 --- a/contracts/proposal/dao-proposal-multiple/src/testing/instantiate.rs +++ b/contracts/proposal/dao-proposal-multiple/src/testing/instantiate.rs @@ -52,8 +52,9 @@ fn get_pre_propose_info( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "pre_propose_contract".to_string(), + salt: None, }, } } @@ -169,15 +170,17 @@ pub fn _instantiate_with_staked_cw721_governance( }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -289,15 +292,17 @@ pub fn instantiate_with_native_staked_balances_governance( }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -403,19 +408,22 @@ pub fn instantiate_with_cw20_balances_governance( decimals: 6, initial_balances, marketing: None, + salt: None, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -490,19 +498,23 @@ pub fn instantiate_with_staked_balances_governance( staking_code_id: cw20_stake_id, unstaking_duration: Some(Duration::Height(6)), initial_dao_balance: None, + salt: None, + staking_salt: None, }, }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -630,19 +642,23 @@ pub fn instantiate_with_multiple_staked_balances_governance( staking_code_id: cw20_stake_id, unstaking_duration: Some(Duration::Height(6)), initial_dao_balance: None, + salt: None, + staking_salt: None, }, }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -745,20 +761,24 @@ pub fn instantiate_with_staking_active_threshold( staking_code_id: cw20_staking_id, unstaking_duration: None, initial_dao_balance: None, + salt: None, + staking_salt: None, }, active_threshold, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -825,20 +845,23 @@ pub fn _instantiate_with_cw4_groups_governance( msg: to_json_binary(&dao_voting_cw4::msg::InstantiateMsg { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, + cw4_group_salt: None, initial_members: initial_weights, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/proposal/dao-proposal-multiple/src/testing/tests.rs b/contracts/proposal/dao-proposal-multiple/src/testing/tests.rs index af7ac3a91..fb1f81682 100644 --- a/contracts/proposal/dao-proposal-multiple/src/testing/tests.rs +++ b/contracts/proposal/dao-proposal-multiple/src/testing/tests.rs @@ -102,8 +102,9 @@ pub fn get_pre_propose_info( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "pre_propose_contract".to_string(), + salt: None, }, } } @@ -1113,6 +1114,7 @@ fn test_bad_token_proposal_deposit() { amount: Uint128::new(1), }], marketing: None, + salt: None, }, }, &[], diff --git a/contracts/proposal/dao-proposal-single/schema/dao-proposal-single.json b/contracts/proposal/dao-proposal-single/schema/dao-proposal-single.json index b719a0a60..19dcefa8b 100644 --- a/contracts/proposal/dao-proposal-single/schema/dao-proposal-single.json +++ b/contracts/proposal/dao-proposal-single/schema/dao-proposal-single.json @@ -186,7 +186,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -210,7 +209,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -226,6 +228,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -1336,7 +1349,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -1360,7 +1372,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -1376,6 +1391,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false @@ -2461,7 +2487,6 @@ "type": "object", "required": [ "code_id", - "funds", "label", "msg" ], @@ -2485,7 +2510,10 @@ }, "funds": { "description": "Funds to be sent to the instantiated contract.", - "type": "array", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/definitions/Coin" } @@ -2501,6 +2529,17 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "description": "Salt to use with instantiate2, if defined. Otherwise uses normal instantiate.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/proposal/dao-proposal-single/src/testing/instantiate.rs b/contracts/proposal/dao-proposal-single/src/testing/instantiate.rs index 8eb72d68f..b2dac1558 100644 --- a/contracts/proposal/dao-proposal-single/src/testing/instantiate.rs +++ b/contracts/proposal/dao-proposal-single/src/testing/instantiate.rs @@ -50,8 +50,9 @@ pub(crate) fn get_pre_propose_info( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "pre_propose_contract".to_string(), + salt: None, }, } } @@ -170,15 +171,17 @@ pub(crate) fn instantiate_with_staked_cw721_governance( }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -290,15 +293,17 @@ pub(crate) fn instantiate_with_native_staked_balances_governance( }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -408,19 +413,23 @@ pub(crate) fn instantiate_with_staked_balances_governance( staking_code_id: cw20_stake_id, unstaking_duration: Some(Duration::Height(6)), initial_dao_balance: None, + salt: None, + staking_salt: None, }, }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module.".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -523,20 +532,24 @@ pub(crate) fn instantiate_with_staking_active_threshold( staking_code_id: cw20_staking_id, unstaking_duration: None, initial_dao_balance: None, + salt: None, + staking_salt: None, }, active_threshold, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -603,20 +616,23 @@ pub(crate) fn instantiate_with_cw4_groups_governance( msg: to_json_binary(&dao_voting_cw4::msg::InstantiateMsg { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, + cw4_group_salt: None, initial_members: initial_weights, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: to_json_binary(&proposal_module_instantiate).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/proposal/dao-proposal-single/src/testing/migration_tests.rs b/contracts/proposal/dao-proposal-single/src/testing/migration_tests.rs index 2aa4ce67e..837fe5bf0 100644 --- a/contracts/proposal/dao-proposal-single/src/testing/migration_tests.rs +++ b/contracts/proposal/dao-proposal-single/src/testing/migration_tests.rs @@ -88,6 +88,8 @@ fn test_v1_v2_full_migration() { staking_code_id: cw20_stake_code, unstaking_duration: None, initial_dao_balance: Some(Uint128::new(100)), + salt: None, + staking_salt: None, }, }) .unwrap(), diff --git a/contracts/proposal/dao-proposal-single/src/testing/tests.rs b/contracts/proposal/dao-proposal-single/src/testing/tests.rs index a6d69c1ef..012957b4a 100644 --- a/contracts/proposal/dao-proposal-single/src/testing/tests.rs +++ b/contracts/proposal/dao-proposal-single/src/testing/tests.rs @@ -3211,15 +3211,17 @@ pub fn test_migrate_updates_version() { // }) // .unwrap(), // admin: None, -// funds: vec![], +// funds: None, // label: "DAO DAO voting module".to_string(), +// salt: None, // }, // proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { // code_id: v1_proposal_single_code, // msg: to_json_binary(&instantiate).unwrap(), // admin: Some(Admin::CoreModule {}), -// funds: vec![], +// funds: None, // label: "DAO DAO governance module.".to_string(), +// salt: None, // }], // initial_items: None, // }; @@ -3996,8 +3998,9 @@ fn test_update_pre_propose_module() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "new pre-propose module".to_string(), + salt: None, }, }, }) diff --git a/contracts/test/dao-proposal-hook-counter/src/tests.rs b/contracts/test/dao-proposal-hook-counter/src/tests.rs index 8dab92c39..8ee032bc0 100644 --- a/contracts/test/dao-proposal-hook-counter/src/tests.rs +++ b/contracts/test/dao-proposal-hook-counter/src/tests.rs @@ -72,19 +72,22 @@ fn instantiate_with_default_governance( decimals: 6, initial_balances, marketing: None, + salt: None, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id, msg: to_json_binary(&msg).unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/test/dao-voting-cw20-balance/src/contract.rs b/contracts/test/dao-voting-cw20-balance/src/contract.rs index 6d75355fd..76031a3f1 100644 --- a/contracts/test/dao-voting-cw20-balance/src/contract.rs +++ b/contracts/test/dao-voting-cw20-balance/src/contract.rs @@ -2,10 +2,11 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg, - Uint128, WasmMsg, + Uint128, }; use cw2::set_contract_version; use cw_utils::parse_reply_instantiate_data; +use dao_interface::state::{Admin, ModuleInstantiateInfo}; use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, TokenInfo}; @@ -38,6 +39,7 @@ pub fn instantiate( } TokenInfo::New { code_id, + salt, label, name, symbol, @@ -52,24 +54,28 @@ pub fn instantiate( return Err(ContractError::InitialBalancesError {}); } - let msg = WasmMsg::Instantiate { - admin: Some(info.sender.to_string()), - code_id, - msg: to_json_binary(&cw20_base::msg::InstantiateMsg { - name, - symbol, - decimals, - initial_balances, - mint: Some(cw20::MinterResponse { - minter: info.sender.to_string(), - cap: None, - }), - marketing, - })?, - funds: vec![], - label, - }; - let msg = SubMsg::reply_on_success(msg, INSTANTIATE_TOKEN_REPLY_ID); + let msg = SubMsg::reply_on_success( + ModuleInstantiateInfo { + admin: Some(Admin::CoreModule {}), + code_id, + msg: to_json_binary(&cw20_base::msg::InstantiateMsg { + name, + symbol, + decimals, + initial_balances, + mint: Some(cw20::MinterResponse { + minter: info.sender.to_string(), + cap: None, + }), + marketing, + })?, + funds: None, + label, + salt, + } + .into_cosmos_msg(info.sender), + INSTANTIATE_TOKEN_REPLY_ID, + ); Ok(Response::default() .add_attribute("action", "instantiate") diff --git a/contracts/test/dao-voting-cw20-balance/src/msg.rs b/contracts/test/dao-voting-cw20-balance/src/msg.rs index c41590ee2..45bc58fc5 100644 --- a/contracts/test/dao-voting-cw20-balance/src/msg.rs +++ b/contracts/test/dao-voting-cw20-balance/src/msg.rs @@ -1,17 +1,21 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Binary; use cw20::Cw20Coin; use cw20_base::msg::InstantiateMarketingInfo; use dao_dao_macros::{cw20_token_query, voting_module_query}; #[cw_serde] +#[allow(clippy::large_enum_variant)] pub enum TokenInfo { Existing { address: String, }, New { code_id: u64, + /// Optionally instantiate the token via instantiate2 using this salt. + salt: Option, label: String, name: String, diff --git a/contracts/test/dao-voting-cw20-balance/src/tests.rs b/contracts/test/dao-voting-cw20-balance/src/tests.rs index 79d1a6cd4..d2e3cdb51 100644 --- a/contracts/test/dao-voting-cw20-balance/src/tests.rs +++ b/contracts/test/dao-voting-cw20-balance/src/tests.rs @@ -43,6 +43,7 @@ fn test_instantiate_zero_supply() { amount: Uint128::zero(), }], marketing: None, + salt: None, }, }, ); @@ -66,6 +67,7 @@ fn test_instantiate_no_balances() { decimals: 6, initial_balances: vec![], marketing: None, + salt: None, }, }, ); @@ -92,6 +94,7 @@ fn test_contract_info() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }, ); @@ -132,6 +135,7 @@ fn test_new_cw20() { amount: Uint128::from(2u64), }], marketing: None, + salt: None, }, }, ); diff --git a/contracts/voting/dao-voting-cw20-staked/schema/dao-voting-cw20-staked.json b/contracts/voting/dao-voting-cw20-staked/schema/dao-voting-cw20-staked.json index b2043550f..71714af19 100644 --- a/contracts/voting/dao-voting-cw20-staked/schema/dao-voting-cw20-staked.json +++ b/contracts/voting/dao-voting-cw20-staked/schema/dao-voting-cw20-staked.json @@ -273,6 +273,17 @@ "format": "uint64", "minimum": 0.0 }, + "staking_salt": { + "description": "Optionally instantiate the staking contract via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "unstaking_duration": { "description": "See corresponding field in cw20-stake's instantiation. This will be used when instantiating the new staking contract.", "anyOf": [ @@ -387,11 +398,33 @@ "name": { "type": "string" }, + "salt": { + "description": "Optionally instantiate the token via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "staking_code_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, + "staking_salt": { + "description": "Optionally instantiate the staking contract via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "symbol": { "type": "string" }, diff --git a/contracts/voting/dao-voting-cw20-staked/src/contract.rs b/contracts/voting/dao-voting-cw20-staked/src/contract.rs index 47913a57c..e001fc58f 100644 --- a/contracts/voting/dao-voting-cw20-staked/src/contract.rs +++ b/contracts/voting/dao-voting-cw20-staked/src/contract.rs @@ -2,11 +2,12 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Addr, Binary, Decimal, Deps, DepsMut, Env, MessageInfo, Reply, Response, - StdResult, SubMsg, Uint128, Uint256, WasmMsg, + StdResult, SubMsg, Uint128, Uint256, }; use cw2::{get_contract_version, set_contract_version, ContractVersion}; use cw20::{Cw20Coin, TokenInfoResponse}; use cw_utils::parse_reply_instantiate_data; +use dao_interface::state::{Admin, ModuleInstantiateInfo}; use dao_interface::voting::IsActiveResponse; use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse}; use std::convert::TryInto; @@ -14,7 +15,7 @@ use std::convert::TryInto; use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, StakingInfo, TokenInfo}; use crate::state::{ - ACTIVE_THRESHOLD, DAO, STAKING_CONTRACT, STAKING_CONTRACT_CODE_ID, + ACTIVE_THRESHOLD, DAO, STAKING_CONTRACT, STAKING_CONTRACT_CODE_ID, STAKING_CONTRACT_SALT, STAKING_CONTRACT_UNSTAKING_DURATION, TOKEN, }; @@ -82,20 +83,25 @@ pub fn instantiate( } StakingInfo::New { staking_code_id, + staking_salt: salt, unstaking_duration, } => { - let msg = WasmMsg::Instantiate { - code_id: staking_code_id, - funds: vec![], - admin: Some(info.sender.to_string()), - label: env.contract.address.to_string(), - msg: to_json_binary(&cw20_stake::msg::InstantiateMsg { - owner: Some(info.sender.to_string()), - unstaking_duration, - token_address: address.to_string(), - })?, - }; - let msg = SubMsg::reply_on_success(msg, INSTANTIATE_STAKING_REPLY_ID); + let msg = SubMsg::reply_on_success( + ModuleInstantiateInfo { + code_id: staking_code_id, + admin: Some(Admin::CoreModule {}), + label: env.contract.address.to_string(), + msg: to_json_binary(&cw20_stake::msg::InstantiateMsg { + owner: Some(info.sender.to_string()), + unstaking_duration, + token_address: address.to_string(), + })?, + funds: None, + salt, + } + .into_cosmos_msg(info.sender), + INSTANTIATE_STAKING_REPLY_ID, + ); Ok(Response::default() .add_attribute("action", "instantiate") .add_attribute("token", "existing_token") @@ -106,6 +112,7 @@ pub fn instantiate( } TokenInfo::New { code_id, + salt, label, name, symbol, @@ -114,6 +121,7 @@ pub fn instantiate( initial_dao_balance, marketing, staking_code_id, + staking_salt, unstaking_duration, } => { let initial_supply = initial_balances @@ -136,26 +144,32 @@ pub fn instantiate( } STAKING_CONTRACT_CODE_ID.save(deps.storage, &staking_code_id)?; + if let Some(staking_salt) = staking_salt { + STAKING_CONTRACT_SALT.save(deps.storage, &staking_salt)?; + } STAKING_CONTRACT_UNSTAKING_DURATION.save(deps.storage, &unstaking_duration)?; - - let msg = WasmMsg::Instantiate { - admin: Some(info.sender.to_string()), - code_id, - msg: to_json_binary(&cw20_base::msg::InstantiateMsg { - name, - symbol, - decimals, - initial_balances, - mint: Some(cw20::MinterResponse { - minter: info.sender.to_string(), - cap: None, - }), - marketing, - })?, - funds: vec![], - label, - }; - let msg = SubMsg::reply_on_success(msg, INSTANTIATE_TOKEN_REPLY_ID); + let msg = SubMsg::reply_on_success( + ModuleInstantiateInfo { + admin: Some(Admin::CoreModule {}), + code_id, + msg: to_json_binary(&cw20_base::msg::InstantiateMsg { + name, + symbol, + decimals, + initial_balances, + mint: Some(cw20::MinterResponse { + minter: info.sender.to_string(), + cap: None, + }), + marketing, + })?, + funds: None, + label, + salt, + } + .into_cosmos_msg(info.sender), + INSTANTIATE_TOKEN_REPLY_ID, + ); Ok(Response::default() .add_attribute("action", "instantiate") @@ -405,21 +419,26 @@ pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result, /// See corresponding field in cw20-stake's /// instantiation. This will be used when instantiating the /// new staking contract. @@ -37,6 +40,8 @@ pub enum TokenInfo { New { /// Code ID for cw20 token contract. code_id: u64, + /// Optionally instantiate the token via instantiate2 using this salt. + salt: Option, /// Label to use for instantiated cw20 contract. label: String, @@ -47,6 +52,9 @@ pub enum TokenInfo { marketing: Option, staking_code_id: u64, + /// Optionally instantiate the staking contract via instantiate2 using + /// this salt. + staking_salt: Option, unstaking_duration: Option, initial_dao_balance: Option, }, diff --git a/contracts/voting/dao-voting-cw20-staked/src/state.rs b/contracts/voting/dao-voting-cw20-staked/src/state.rs index d4e61d397..d9dd688fa 100644 --- a/contracts/voting/dao-voting-cw20-staked/src/state.rs +++ b/contracts/voting/dao-voting-cw20-staked/src/state.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::Addr; +use cosmwasm_std::{Addr, Binary}; use cw_storage_plus::Item; use cw_utils::Duration; use dao_voting::threshold::ActiveThreshold; @@ -10,3 +10,4 @@ pub const STAKING_CONTRACT: Item = Item::new("staking_contract"); pub const STAKING_CONTRACT_UNSTAKING_DURATION: Item> = Item::new("staking_contract_unstaking_duration"); pub const STAKING_CONTRACT_CODE_ID: Item = Item::new("staking_contract_code_id"); +pub const STAKING_CONTRACT_SALT: Item = Item::new("staking_contract_salt"); diff --git a/contracts/voting/dao-voting-cw20-staked/src/tests.rs b/contracts/voting/dao-voting-cw20-staked/src/tests.rs index 1ba100fb0..ce084d48c 100644 --- a/contracts/voting/dao-voting-cw20-staked/src/tests.rs +++ b/contracts/voting/dao-voting-cw20-staked/src/tests.rs @@ -66,6 +66,8 @@ fn test_instantiate_zero_supply() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::zero()), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -94,6 +96,8 @@ fn test_instantiate_no_balances() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::zero()), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -125,6 +129,8 @@ fn test_instantiate_zero_active_threshold_count() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::zero()), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::AbsoluteCount { count: Uint128::new(0), @@ -158,6 +164,8 @@ fn test_contract_info() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::zero()), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -209,6 +217,8 @@ fn test_new_cw20() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(10u64)), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -381,6 +391,7 @@ fn test_existing_cw20_new_staking() { address: token_addr.to_string(), staking_contract: StakingInfo::New { staking_code_id: staking_id, + staking_salt: None, unstaking_duration: None, }, }, @@ -532,6 +543,7 @@ fn test_existing_cw20_existing_staking() { address: token_addr.to_string(), staking_contract: StakingInfo::New { staking_code_id: staking_id, + staking_salt: None, unstaking_duration: None, }, }, @@ -733,6 +745,7 @@ fn test_different_heights() { address: token_addr.to_string(), staking_contract: StakingInfo::New { staking_code_id: staking_id, + staking_salt: None, unstaking_duration: None, }, }, @@ -922,6 +935,8 @@ fn test_active_threshold_absolute_count() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::AbsoluteCount { count: Uint128::new(100), @@ -982,6 +997,8 @@ fn test_active_threshold_percent() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::Percentage { percent: Decimal::percent(20), @@ -1042,6 +1059,8 @@ fn test_active_threshold_percent_rounds_up() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: None, + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::Percentage { percent: Decimal::percent(50), @@ -1117,6 +1136,8 @@ fn test_active_threshold_none() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -1155,6 +1176,8 @@ fn test_update_active_threshold() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: None, }, @@ -1223,6 +1246,8 @@ fn test_active_threshold_percentage_gt_100() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::Percentage { percent: Decimal::percent(120), @@ -1257,6 +1282,8 @@ fn test_active_threshold_percentage_lte_0() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::Percentage { percent: Decimal::percent(0), @@ -1291,6 +1318,8 @@ fn test_active_threshold_absolute_count_invalid() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::from(100u64)), + salt: None, + staking_salt: None, }, active_threshold: Some(ActiveThreshold::AbsoluteCount { count: Uint128::new(10000), @@ -1325,6 +1354,8 @@ fn test_migrate() { unstaking_duration: None, staking_code_id: staking_contract_id, initial_dao_balance: Some(Uint128::zero()), + salt: None, + staking_salt: None, }, active_threshold: None, }, diff --git a/contracts/voting/dao-voting-cw4/Cargo.toml b/contracts/voting/dao-voting-cw4/Cargo.toml index 9120acf99..d67fe0315 100644 --- a/contracts/voting/dao-voting-cw4/Cargo.toml +++ b/contracts/voting/dao-voting-cw4/Cargo.toml @@ -26,7 +26,7 @@ thiserror = { workspace = true } dao-dao-macros = { workspace = true } dao-interface = { workspace = true } cw4 = { workspace = true } -cw4-group = { workspace = true } +cw4-group = { workspace = true, features = ["library"] } [dev-dependencies] dao-voting-cw4 = { workspace = true } diff --git a/contracts/voting/dao-voting-cw4/schema/dao-voting-cw4.json b/contracts/voting/dao-voting-cw4/schema/dao-voting-cw4.json index 5e785bb41..1f870b783 100644 --- a/contracts/voting/dao-voting-cw4/schema/dao-voting-cw4.json +++ b/contracts/voting/dao-voting-cw4/schema/dao-voting-cw4.json @@ -16,6 +16,10 @@ }, "additionalProperties": false, "definitions": { + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, "GroupContract": { "oneOf": [ { @@ -57,6 +61,17 @@ "format": "uint64", "minimum": 0.0 }, + "cw4_group_salt": { + "description": "Optionally instantiate the cw4 group via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "initial_members": { "type": "array", "items": { diff --git a/contracts/voting/dao-voting-cw4/src/contract.rs b/contracts/voting/dao-voting-cw4/src/contract.rs index 48307676f..745991fd6 100644 --- a/contracts/voting/dao-voting-cw4/src/contract.rs +++ b/contracts/voting/dao-voting-cw4/src/contract.rs @@ -2,11 +2,12 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg, - Uint128, WasmMsg, + Uint128, }; use cw2::{get_contract_version, set_contract_version, ContractVersion}; use cw4::{MemberListResponse, MemberResponse, TotalWeightResponse}; use cw_utils::parse_reply_instantiate_data; +use dao_interface::state::{Admin, ModuleInstantiateInfo}; use crate::error::ContractError; use crate::msg::{ExecuteMsg, GroupContract, InstantiateMsg, MigrateMsg, QueryMsg}; @@ -31,6 +32,7 @@ pub fn instantiate( match msg.group_contract { GroupContract::New { cw4_group_code_id, + cw4_group_salt, initial_members, } => { if initial_members.is_empty() { @@ -64,18 +66,21 @@ pub fn instantiate( // Instantiate group contract, set DAO as admin. // Voting module contracts are instantiated by the main dao-dao-core // contract, so the Admin is set to info.sender. - let msg = WasmMsg::Instantiate { - admin: Some(info.sender.to_string()), - code_id: cw4_group_code_id, - msg: to_json_binary(&cw4_group::msg::InstantiateMsg { - admin: Some(info.sender.to_string()), - members: initial_members, - })?, - funds: vec![], - label: env.contract.address.to_string(), - }; - - let msg = SubMsg::reply_on_success(msg, INSTANTIATE_GROUP_REPLY_ID); + let msg = SubMsg::reply_on_success( + ModuleInstantiateInfo { + admin: Some(Admin::CoreModule {}), + code_id: cw4_group_code_id, + msg: to_json_binary(&cw4_group::msg::InstantiateMsg { + admin: Some(info.sender.to_string()), + members: initial_members, + })?, + funds: None, + label: env.contract.address.to_string(), + salt: cw4_group_salt, + } + .into_cosmos_msg(info.sender), + INSTANTIATE_GROUP_REPLY_ID, + ); Ok(Response::new() .add_attribute("action", "instantiate") diff --git a/contracts/voting/dao-voting-cw4/src/msg.rs b/contracts/voting/dao-voting-cw4/src/msg.rs index 24bd0eebc..3c60ae0a3 100644 --- a/contracts/voting/dao-voting-cw4/src/msg.rs +++ b/contracts/voting/dao-voting-cw4/src/msg.rs @@ -1,4 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Binary; use dao_dao_macros::voting_module_query; #[cw_serde] @@ -8,6 +9,9 @@ pub enum GroupContract { }, New { cw4_group_code_id: u64, + /// Optionally instantiate the cw4 group via instantiate2 using this + /// salt. + cw4_group_salt: Option, initial_members: Vec, }, } diff --git a/contracts/voting/dao-voting-cw4/src/tests.rs b/contracts/voting/dao-voting-cw4/src/tests.rs index 9ada195e2..72ec9b13d 100644 --- a/contracts/voting/dao-voting-cw4/src/tests.rs +++ b/contracts/voting/dao-voting-cw4/src/tests.rs @@ -61,6 +61,7 @@ fn setup_test_case(app: &mut App) -> Addr { InstantiateMsg { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, + cw4_group_salt: None, initial_members: members, }, }, @@ -80,6 +81,7 @@ fn test_instantiate() { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, initial_members: [].into(), + cw4_group_salt: None, }, }; let _err = app @@ -111,6 +113,7 @@ fn test_instantiate() { weight: 0, }, ], + cw4_group_salt: None, }, }; let _err = app @@ -560,6 +563,7 @@ fn test_migrate() { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, initial_members, + cw4_group_salt: None, }, }; let voting_addr = app @@ -637,6 +641,7 @@ fn test_duplicate_member() { weight: 19, }, ], + cw4_group_salt: None, }, }; // Previous versions voting power was 100, due to no dedup. diff --git a/contracts/voting/dao-voting-cw721-roles/schema/dao-voting-cw721-roles.json b/contracts/voting/dao-voting-cw721-roles/schema/dao-voting-cw721-roles.json index b73565bb0..401385358 100644 --- a/contracts/voting/dao-voting-cw721-roles/schema/dao-voting-cw721-roles.json +++ b/contracts/voting/dao-voting-cw721-roles/schema/dao-voting-cw721-roles.json @@ -21,6 +21,10 @@ }, "additionalProperties": false, "definitions": { + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, "MetadataExt": { "type": "object", "required": [ @@ -104,6 +108,17 @@ "description": "NFT collection name", "type": "string" }, + "salt": { + "description": "Optionally instantiate the token via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, "symbol": { "description": "NFT collection symbol", "type": "string" diff --git a/contracts/voting/dao-voting-cw721-roles/src/contract.rs b/contracts/voting/dao-voting-cw721-roles/src/contract.rs index d44bf10ab..3ce12335e 100644 --- a/contracts/voting/dao-voting-cw721-roles/src/contract.rs +++ b/contracts/voting/dao-voting-cw721-roles/src/contract.rs @@ -12,6 +12,7 @@ use cw721_base::{ use cw_ownable::Action; use cw_utils::parse_reply_instantiate_data; use dao_cw721_extensions::roles::{ExecuteExt, MetadataExt, QueryExt}; +use dao_interface::state::{Admin, ModuleInstantiateInfo}; use crate::msg::{ExecuteMsg, InstantiateMsg, NftContract, QueryMsg}; use crate::state::{Config, CONFIG, DAO, INITIAL_NFTS}; @@ -46,6 +47,7 @@ pub fn instantiate( } NftContract::New { code_id, + salt, label, name, symbol, @@ -61,10 +63,9 @@ pub fn instantiate( // Create instantiate submessage for NFT roles contract let msg = SubMsg::reply_on_success( - WasmMsg::Instantiate { + ModuleInstantiateInfo { code_id, - funds: vec![], - admin: Some(info.sender.to_string()), + admin: Some(Admin::CoreModule {}), label, msg: to_json_binary(&Cw721InstantiateMsg { name, @@ -72,7 +73,10 @@ pub fn instantiate( // Admin must be set to contract to mint initial NFTs minter: env.contract.address.to_string(), })?, - }, + funds: None, + salt, + } + .into_cosmos_msg(info.sender), INSTANTIATE_NFT_CONTRACT_REPLY_ID, ); diff --git a/contracts/voting/dao-voting-cw721-roles/src/msg.rs b/contracts/voting/dao-voting-cw721-roles/src/msg.rs index b15099529..91d4c4dd2 100644 --- a/contracts/voting/dao-voting-cw721-roles/src/msg.rs +++ b/contracts/voting/dao-voting-cw721-roles/src/msg.rs @@ -1,4 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Binary; use dao_cw721_extensions::roles::MetadataExt; use dao_dao_macros::voting_module_query; @@ -25,6 +26,8 @@ pub enum NftContract { New { /// Code ID for cw721 token contract. code_id: u64, + /// Optionally instantiate the token via instantiate2 using this salt. + salt: Option, /// Label to use for instantiated cw721 contract. label: String, /// NFT collection name diff --git a/contracts/voting/dao-voting-cw721-roles/src/testing/mod.rs b/contracts/voting/dao-voting-cw721-roles/src/testing/mod.rs index 98cebccd9..984928a81 100644 --- a/contracts/voting/dao-voting-cw721-roles/src/testing/mod.rs +++ b/contracts/voting/dao-voting-cw721-roles/src/testing/mod.rs @@ -35,6 +35,7 @@ pub(crate) fn setup_test(initial_nfts: Vec) -> CommonTest { name: "Job Titles".to_string(), symbol: "TITLES".to_string(), initial_nfts, + salt: None, }, }, &[], diff --git a/contracts/voting/dao-voting-cw721-staked/schema/dao-voting-cw721-staked.json b/contracts/voting/dao-voting-cw721-staked/schema/dao-voting-cw721-staked.json index 396c520d9..c2ebe89ee 100644 --- a/contracts/voting/dao-voting-cw721-staked/schema/dao-voting-cw721-staked.json +++ b/contracts/voting/dao-voting-cw721-staked/schema/dao-voting-cw721-staked.json @@ -194,6 +194,17 @@ }, "msg": { "$ref": "#/definitions/Binary" + }, + "salt": { + "description": "Optionally instantiate the token via instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/voting/dao-voting-cw721-staked/src/contract.rs b/contracts/voting/dao-voting-cw721-staked/src/contract.rs index 53f574c24..f4d2ae4c3 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/contract.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/contract.rs @@ -9,7 +9,7 @@ use cw721::{Cw721QueryMsg, Cw721ReceiveMsg, NumTokensResponse}; use cw_storage_plus::Bound; use cw_utils::{parse_reply_execute_data, parse_reply_instantiate_data, Duration}; use dao_hooks::nft_stake::{stake_nft_hook_msgs, unstake_nft_hook_msgs}; -use dao_interface::state::ModuleInstantiateCallback; +use dao_interface::state::{Admin, ModuleInstantiateCallback, ModuleInstantiateInfo}; use dao_interface::{nft::NftFactoryCallback, voting::IsActiveResponse}; use dao_voting::duration::validate_duration; use dao_voting::threshold::{ @@ -124,6 +124,7 @@ pub fn instantiate( } NftContract::New { code_id, + salt, label, msg: instantiate_msg, initial_nfts, @@ -152,13 +153,15 @@ pub fn instantiate( // Create instantiate submessage for NFT contract let instantiate_msg = SubMsg::reply_on_success( - WasmMsg::Instantiate { + ModuleInstantiateInfo { code_id, - funds: vec![], - admin: Some(info.sender.to_string()), + admin: Some(Admin::CoreModule {}), label, msg: instantiate_msg.to_json_binary()?, - }, + funds: None, + salt, + } + .into_cosmos_msg(info.sender), INSTANTIATE_NFT_CONTRACT_REPLY_ID, ); diff --git a/contracts/voting/dao-voting-cw721-staked/src/msg.rs b/contracts/voting/dao-voting-cw721-staked/src/msg.rs index 62ca2efd4..c3ffbdd77 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/msg.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/msg.rs @@ -17,6 +17,8 @@ pub enum NftContract { New { /// Code ID for cw721 token contract. code_id: u64, + /// Optionally instantiate the token via instantiate2 using this salt. + salt: Option, /// Label to use for instantiated cw721 contract. label: String, msg: Binary, diff --git a/contracts/voting/dao-voting-cw721-staked/src/testing/integration_tests.rs b/contracts/voting/dao-voting-cw721-staked/src/testing/integration_tests.rs index 177088220..291b727e1 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/testing/integration_tests.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/testing/integration_tests.rs @@ -98,6 +98,7 @@ fn test_full_integration_with_factory() { denom: "uosmo".to_string(), }], label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single.code_id, @@ -119,6 +120,7 @@ fn test_full_integration_with_factory() { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/voting/dao-voting-cw721-staked/src/testing/test_tube_env.rs b/contracts/voting/dao-voting-cw721-staked/src/testing/test_tube_env.rs index 54b48b565..fdc670755 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/testing/test_tube_env.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/testing/test_tube_env.rs @@ -122,6 +122,7 @@ impl TestEnvBuilder { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -143,6 +144,7 @@ impl TestEnvBuilder { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs b/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs index 619aee4ab..3459830d4 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs @@ -49,6 +49,7 @@ fn test_instantiate_with_new_cw721_collection() -> anyhow::Result<()> { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -586,6 +587,7 @@ fn test_instantiate_with_invalid_duration_fails() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -625,6 +627,7 @@ fn test_instantiate_zero_active_threshold_count() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -665,6 +668,7 @@ fn test_instantiate_invalid_active_threshold_count_new_nft() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -731,6 +735,7 @@ fn test_active_threshold_absolute_count() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -811,6 +816,7 @@ fn test_active_threshold_percent() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -872,6 +878,7 @@ fn test_active_threshold_percent_rounds_up() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -974,6 +981,7 @@ fn test_update_active_threshold() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -1050,6 +1058,7 @@ fn test_active_threshold_percentage_gt_100() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -1092,6 +1101,7 @@ fn test_active_threshold_percentage_lte_0() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -1132,6 +1142,7 @@ fn test_invalid_instantiate_msg() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Empty {}).unwrap(), initial_nfts: vec![to_json_binary(&Cw721ExecuteMsg::::Mint { @@ -1171,6 +1182,7 @@ fn test_invalid_initial_nft_msg() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -1210,6 +1222,7 @@ fn test_invalid_initial_nft_msg_wrong_absolute_count() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), @@ -1260,6 +1273,7 @@ fn test_no_initial_nfts_fails() { &InstantiateMsg { nft_contract: NftContract::New { code_id: cw721_id, + salt: None, label: "Test NFT".to_string(), msg: to_json_binary(&Cw721InstantiateMsg { name: "Test NFT".to_string(), diff --git a/contracts/voting/dao-voting-token-staked/schema/dao-voting-token-staked.json b/contracts/voting/dao-voting-token-staked/schema/dao-voting-token-staked.json index 0ef91a60f..36f1e0898 100644 --- a/contracts/voting/dao-voting-token-staked/schema/dao-voting-token-staked.json +++ b/contracts/voting/dao-voting-token-staked/schema/dao-voting-token-staked.json @@ -262,6 +262,17 @@ "type": "integer", "format": "uint64", "minimum": 0.0 + }, + "token_issuer_salt": { + "description": "Optionally instantiate the cw-tokenfactory-issuer contract with instantiate2 using this salt.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false diff --git a/contracts/voting/dao-voting-token-staked/src/contract.rs b/contracts/voting/dao-voting-token-staked/src/contract.rs index 33b85db11..c218caee2 100644 --- a/contracts/voting/dao-voting-token-staked/src/contract.rs +++ b/contracts/voting/dao-voting-token-staked/src/contract.rs @@ -20,7 +20,7 @@ use cw_utils::{ }; use dao_hooks::stake::{stake_hook_msgs, unstake_hook_msgs}; use dao_interface::{ - state::ModuleInstantiateCallback, + state::{Admin, ModuleInstantiateCallback, ModuleInstantiateInfo}, token::{InitialBalance, NewTokenInfo, TokenFactoryCallback}, voting::{ DenomResponse, IsActiveResponse, TotalPowerAtHeightResponse, VotingPowerAtHeightResponse, @@ -106,6 +106,7 @@ pub fn instantiate( let NewTokenInfo { subdenom, token_issuer_code_id, + token_issuer_salt, .. } = token; @@ -115,15 +116,17 @@ pub fn instantiate( // Instantiate cw-token-factory-issuer contract // DAO (sender) is set as contract admin let issuer_instantiate_msg = SubMsg::reply_on_success( - WasmMsg::Instantiate { - admin: Some(info.sender.to_string()), + ModuleInstantiateInfo { + admin: Some(Admin::CoreModule {}), code_id: *token_issuer_code_id, msg: to_json_binary(&IssuerInstantiateMsg::NewToken { subdenom: subdenom.to_string(), })?, - funds: info.funds, + funds: Some(info.funds), label: "cw-tokenfactory-issuer".to_string(), - }, + salt: token_issuer_salt.clone(), + } + .into_cosmos_msg(info.sender), INSTANTIATE_TOKEN_FACTORY_ISSUER_REPLY_ID, ); diff --git a/contracts/voting/dao-voting-token-staked/src/msg.rs b/contracts/voting/dao-voting-token-staked/src/msg.rs index 98809ec9e..c6cd0750d 100644 --- a/contracts/voting/dao-voting-token-staked/src/msg.rs +++ b/contracts/voting/dao-voting-token-staked/src/msg.rs @@ -6,6 +6,7 @@ use dao_interface::token::NewTokenInfo; use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse}; #[cw_serde] +#[allow(clippy::large_enum_variant)] pub enum TokenInfo { /// Uses an existing Token Factory token and creates a new issuer contract. /// Full setup, such as transferring ownership or setting up MsgSetBeforeSendHook, diff --git a/contracts/voting/dao-voting-token-staked/src/tests/test_tube/integration_tests.rs b/contracts/voting/dao-voting-token-staked/src/tests/test_tube/integration_tests.rs index f175ecad0..22b7778c0 100644 --- a/contracts/voting/dao-voting-token-staked/src/tests/test_tube/integration_tests.rs +++ b/contracts/voting/dao-voting-token-staked/src/tests/test_tube/integration_tests.rs @@ -382,6 +382,7 @@ fn test_factory() { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single.unwrap().code_id, @@ -403,6 +404,7 @@ fn test_factory() { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -494,6 +496,7 @@ fn test_factory_funds_pass_through() { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single.unwrap().code_id, @@ -515,6 +518,7 @@ fn test_factory_funds_pass_through() { admin: Some(Admin::CoreModule {}), funds: vec![], label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -570,6 +574,7 @@ fn test_factory_funds_pass_through() { admin: Some(Admin::CoreModule {}), funds: funds.clone(), label: "DAO DAO Voting Module".to_string(), + salt: None, }; // Creating the DAO now succeeds @@ -620,8 +625,9 @@ fn test_factory_no_callback() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single.unwrap().code_id, @@ -641,8 +647,9 @@ fn test_factory_no_callback() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -692,7 +699,7 @@ fn test_factory_wrong_callback() { &dao_test_custom_factory::msg::ExecuteMsg::TokenFactoryFactoryWrongCallback{}, ) .unwrap(), - funds: vec![], + funds: None, }) .unwrap(), ), @@ -703,8 +710,9 @@ fn test_factory_wrong_callback() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single.unwrap().code_id, @@ -724,8 +732,9 @@ fn test_factory_wrong_callback() { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/contracts/voting/dao-voting-token-staked/src/tests/test_tube/test_env.rs b/contracts/voting/dao-voting-token-staked/src/tests/test_tube/test_env.rs index 6f743a769..137139f9a 100644 --- a/contracts/voting/dao-voting-token-staked/src/tests/test_tube/test_env.rs +++ b/contracts/voting/dao-voting-token-staked/src/tests/test_tube/test_env.rs @@ -231,8 +231,9 @@ impl TestEnvBuilder { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Voting Module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_single_id, @@ -252,8 +253,9 @@ impl TestEnvBuilder { }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO Proposal Module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/packages/cw-snapshot-vector-map/src/lib.rs b/packages/cw-snapshot-vector-map/src/lib.rs index b37bf7688..3ab90ac85 100644 --- a/packages/cw-snapshot-vector-map/src/lib.rs +++ b/packages/cw-snapshot-vector-map/src/lib.rs @@ -113,9 +113,8 @@ where let mut active = self.active.may_load(store, k.clone())?.unwrap_or_default(); // remove expired items - active.retain(|(_, expiration)| { - expiration.map_or(true, |expiration| expiration > curr_height) - }); + active + .retain(|(_, expiration)| expiration.is_none_or(|expiration| expiration > curr_height)); // add new item and save list let expiration = expire_in.map(|d| curr_height + d); @@ -149,7 +148,7 @@ where // remove item and any expired items active.retain(|(active_id, expiration)| { - active_id != &id && expiration.map_or(true, |expiration| expiration > curr_height) + active_id != &id && expiration.is_none_or(|expiration| expiration > curr_height) }); // save the new list @@ -209,7 +208,7 @@ where // load paged items, skipping expired ones let items = active_ids .iter() - .filter(|(_, expiration)| expiration.map_or(true, |exp| exp > height)) + .filter(|(_, expiration)| expiration.is_none_or(|exp| exp > height)) .skip(offset) .take(limit) .map(|(id, expiration)| -> StdResult> { @@ -260,7 +259,7 @@ where // load paged items, skipping expired ones let items = active_ids .iter() - .filter(|(_, expiration)| expiration.map_or(true, |exp| exp > current_height)) + .filter(|(_, expiration)| expiration.is_none_or(|exp| exp > current_height)) .skip(offset) .take(limit) .map(|(id, expiration)| -> StdResult> { diff --git a/packages/dao-interface/src/msg.rs b/packages/dao-interface/src/msg.rs index 6f65b46f5..abe7cc5fb 100644 --- a/packages/dao-interface/src/msg.rs +++ b/packages/dao-interface/src/msg.rs @@ -49,7 +49,7 @@ pub struct InstantiateMsg { /// It is an error to provide two items with the same key. pub initial_items: Option>, /// Actions for the DAO to execute immediately. - pub initial_actions: Option>, + pub initial_actions: Option>>, /// Implements the DAO Star standard: pub dao_uri: Option, diff --git a/packages/dao-interface/src/state.rs b/packages/dao-interface/src/state.rs index 2022640eb..b803235a9 100644 --- a/packages/dao-interface/src/state.rs +++ b/packages/dao-interface/src/state.rs @@ -61,24 +61,43 @@ pub struct ModuleInstantiateInfo { /// pub admin: Option, /// Funds to be sent to the instantiated contract. - pub funds: Vec, + pub funds: Option>, /// Label for the instantiated contract. pub label: String, + /// Salt to use with instantiate2, if defined. Otherwise uses normal + /// instantiate. + pub salt: Option, } impl ModuleInstantiateInfo { - pub fn into_wasm_msg(self, dao: Addr) -> WasmMsg { - WasmMsg::Instantiate { - admin: self.admin.map(|admin| match admin { - Admin::Address { addr } => addr, - Admin::CoreModule {} => dao.into_string(), - }), - code_id: self.code_id, - msg: self.msg, - funds: self.funds, - label: self.label, + pub fn into_wasm_msg(self, dao: impl Into) -> WasmMsg { + let admin = self.admin.map(|admin| match admin { + Admin::Address { addr } => addr, + Admin::CoreModule {} => dao.into(), + }); + + match self.salt { + Some(salt) => WasmMsg::Instantiate2 { + admin, + code_id: self.code_id, + msg: self.msg, + funds: self.funds.unwrap_or_default(), + label: self.label, + salt, + }, + None => WasmMsg::Instantiate { + admin, + code_id: self.code_id, + msg: self.msg, + funds: self.funds.unwrap_or_default(), + label: self.label, + }, } } + + pub fn into_cosmos_msg(self, dao: impl Into) -> CosmosMsg { + self.into_wasm_msg(dao).into() + } } /// Callbacks to be executed when a module is instantiated @@ -91,7 +110,7 @@ pub struct ModuleInstantiateCallback { mod tests { use super::*; - use cosmwasm_std::{to_json_binary, Addr, WasmMsg}; + use cosmwasm_std::{coins, to_json_binary, Addr, Uint128, WasmMsg}; #[test] fn test_module_instantiate_admin_none() { @@ -100,7 +119,8 @@ mod tests { msg: to_json_binary("foo").unwrap(), admin: None, label: "bar".to_string(), - funds: vec![], + funds: Some(coins(100, "uatom")), + salt: None, }; assert_eq!( no_admin.into_wasm_msg(Addr::unchecked("ekez")), @@ -108,7 +128,10 @@ mod tests { admin: None, code_id: 42, msg: to_json_binary("foo").unwrap(), - funds: vec![], + funds: vec![Coin { + denom: "uatom".to_string(), + amount: Uint128::from(100u64), + }], label: "bar".to_string() } ) @@ -123,7 +146,8 @@ mod tests { addr: "core".to_string(), }), label: "bar".to_string(), - funds: vec![], + funds: None, + salt: None, }; assert_eq!( no_admin.into_wasm_msg(Addr::unchecked("ekez")), @@ -144,7 +168,8 @@ mod tests { msg: to_json_binary("foo").unwrap(), admin: Some(Admin::CoreModule {}), label: "bar".to_string(), - funds: vec![], + funds: None, + salt: None, }; assert_eq!( no_admin.into_wasm_msg(Addr::unchecked("ekez")), @@ -157,4 +182,78 @@ mod tests { } ) } + + #[test] + fn test_module_instantiate2_admin_none() { + let no_admin = ModuleInstantiateInfo { + code_id: 42, + msg: to_json_binary("foo").unwrap(), + admin: None, + label: "bar".to_string(), + funds: Some(coins(100, "uatom")), + salt: Some(to_json_binary("test_salt").unwrap()), + }; + assert_eq!( + no_admin.into_wasm_msg(Addr::unchecked("ekez")), + WasmMsg::Instantiate2 { + admin: None, + code_id: 42, + msg: to_json_binary("foo").unwrap(), + funds: vec![Coin { + denom: "uatom".to_string(), + amount: Uint128::from(100u64), + }], + label: "bar".to_string(), + salt: to_json_binary("test_salt").unwrap() + } + ) + } + + #[test] + fn test_module_instantiate2_admin_addr() { + let no_admin = ModuleInstantiateInfo { + code_id: 42, + msg: to_json_binary("foo").unwrap(), + admin: Some(Admin::Address { + addr: "core".to_string(), + }), + label: "bar".to_string(), + funds: None, + salt: Some(to_json_binary("test_salt").unwrap()), + }; + assert_eq!( + no_admin.into_wasm_msg(Addr::unchecked("ekez")), + WasmMsg::Instantiate2 { + admin: Some("core".to_string()), + code_id: 42, + msg: to_json_binary("foo").unwrap(), + funds: vec![], + label: "bar".to_string(), + salt: to_json_binary("test_salt").unwrap() + } + ) + } + + #[test] + fn test_module_instantiate2_instantiator_addr() { + let no_admin = ModuleInstantiateInfo { + code_id: 42, + msg: to_json_binary("foo").unwrap(), + admin: Some(Admin::CoreModule {}), + label: "bar".to_string(), + funds: None, + salt: Some(to_json_binary("test_salt").unwrap()), + }; + assert_eq!( + no_admin.into_wasm_msg(Addr::unchecked("ekez")), + WasmMsg::Instantiate2 { + admin: Some("ekez".to_string()), + code_id: 42, + msg: to_json_binary("foo").unwrap(), + funds: vec![], + label: "bar".to_string(), + salt: to_json_binary("test_salt").unwrap() + } + ) + } } diff --git a/packages/dao-interface/src/token.rs b/packages/dao-interface/src/token.rs index c735a15c4..fdddda5a4 100644 --- a/packages/dao-interface/src/token.rs +++ b/packages/dao-interface/src/token.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::cw_serde; -use cosmwasm_std::Uint128; +use cosmwasm_std::{Binary, Uint128}; // These are Cosmos Proto types used for Denom Metadata. // We re-export them here for convenience. @@ -32,6 +32,9 @@ pub struct NewDenomMetadata { pub struct NewTokenInfo { /// The code id of the cw-tokenfactory-issuer contract pub token_issuer_code_id: u64, + /// Optionally instantiate the cw-tokenfactory-issuer contract with + /// instantiate2 using this salt. + pub token_issuer_salt: Option, /// The subdenom of the token to create, will also be used as an alias /// for the denom. The Token Factory denom will have the format of /// factory/{contract_address}/{subdenom} diff --git a/packages/dao-testing/src/helpers.rs b/packages/dao-testing/src/helpers.rs index 504c42e0d..cd285879d 100644 --- a/packages/dao-testing/src/helpers.rs +++ b/packages/dao-testing/src/helpers.rs @@ -59,6 +59,7 @@ pub fn instantiate_with_cw20_balances_governance( msg: to_json_binary(&dao_voting_cw20_balance::msg::InstantiateMsg { token_info: dao_voting_cw20_balance::msg::TokenInfo::New { code_id: cw20_id, + salt: None, label: "DAO DAO governance token".to_string(), name: "DAO".to_string(), symbol: "DAO".to_string(), @@ -69,15 +70,17 @@ pub fn instantiate_with_cw20_balances_governance( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: governance_code_id, msg: governance_instantiate, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -142,6 +145,7 @@ pub fn instantiate_with_staked_balances_governance( active_threshold: None, token_info: dao_voting_cw20_staked::msg::TokenInfo::New { code_id: cw20_id, + salt: None, label: "DAO DAO governance token.".to_string(), name: "DAO DAO".to_string(), symbol: "DAO".to_string(), @@ -149,21 +153,24 @@ pub fn instantiate_with_staked_balances_governance( initial_balances: initial_balances.clone(), marketing: None, staking_code_id: cw20_stake_id, + staking_salt: None, unstaking_duration: Some(Duration::Height(6)), initial_dao_balance: None, }, }) .unwrap(), admin: None, - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: governance_code_id, label: "DAO DAO governance module.".to_string(), admin: Some(Admin::CoreModule {}), msg: governance_instantiate, - funds: vec![], + funds: None, + salt: None, }], initial_items: None, initial_actions: None, @@ -263,6 +270,7 @@ pub fn instantiate_with_staking_active_threshold( msg: to_json_binary(&dao_voting_cw20_staked::msg::InstantiateMsg { token_info: dao_voting_cw20_staked::msg::TokenInfo::New { code_id: cw20_id, + salt: None, label: "DAO DAO governance token".to_string(), name: "DAO".to_string(), symbol: "DAO".to_string(), @@ -270,6 +278,7 @@ pub fn instantiate_with_staking_active_threshold( initial_balances, marketing: None, staking_code_id: cw20_staking_id, + staking_salt: None, unstaking_duration: None, initial_dao_balance: None, }, @@ -277,15 +286,17 @@ pub fn instantiate_with_staking_active_threshold( }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id, msg: governance_instantiate, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, @@ -347,20 +358,23 @@ pub fn instantiate_with_cw4_groups_governance( msg: to_json_binary(&dao_voting_cw4::msg::InstantiateMsg { group_contract: GroupContract::New { cw4_group_code_id: cw4_id, + cw4_group_salt: None, initial_members: initial_weights, }, }) .unwrap(), admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO voting module".to_string(), + salt: None, }, proposal_modules_instantiate_info: vec![ModuleInstantiateInfo { code_id: proposal_module_code_id, msg: proposal_module_instantiate, admin: Some(Admin::CoreModule {}), - funds: vec![], + funds: None, label: "DAO DAO governance module".to_string(), + salt: None, }], initial_items: None, initial_actions: None, diff --git a/packages/dao-testing/src/suite/base.rs b/packages/dao-testing/src/suite/base.rs index 59ad3b6a7..1c274f225 100644 --- a/packages/dao-testing/src/suite/base.rs +++ b/packages/dao-testing/src/suite/base.rs @@ -101,8 +101,9 @@ pub trait DaoTestingSuite: Deref + DerefMut { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "single choice pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: true, @@ -111,8 +112,9 @@ pub trait DaoTestingSuite: Deref + DerefMut { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "single choice proposal module".to_string(), + salt: None, }, dao_interface::state::ModuleInstantiateInfo { code_id: self.base().proposal_multiple_id, @@ -139,8 +141,9 @@ pub trait DaoTestingSuite: Deref + DerefMut { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "multiple choice pre-propose module".to_string(), + salt: None, }, }, close_proposal_on_execution_failure: true, @@ -149,8 +152,9 @@ pub trait DaoTestingSuite: Deref + DerefMut { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "multiple choice proposal module".to_string(), + salt: None, }]; // create the DAO using the base testing suite diff --git a/packages/dao-testing/src/suite/cw20_suite.rs b/packages/dao-testing/src/suite/cw20_suite.rs index 94cf94eec..f46891c63 100644 --- a/packages/dao-testing/src/suite/cw20_suite.rs +++ b/packages/dao-testing/src/suite/cw20_suite.rs @@ -158,6 +158,7 @@ impl DaoTestingSuite for DaoTestingSuiteCw20<'_> { msg: to_json_binary(&dao_voting_cw20_staked::msg::InstantiateMsg { token_info: dao_voting_cw20_staked::msg::TokenInfo::New { code_id: self.cw20_base_id, + salt: None, label: "voting token".to_string(), name: "Voting Token".to_string(), symbol: "VOTE".to_string(), @@ -165,6 +166,7 @@ impl DaoTestingSuite for DaoTestingSuiteCw20<'_> { initial_balances: self.initial_balances.clone(), marketing: None, staking_code_id: self.cw20_stake_id, + staking_salt: None, unstaking_duration: self.unstaking_duration, initial_dao_balance: Some(self.initial_dao_balance), }, @@ -172,8 +174,9 @@ impl DaoTestingSuite for DaoTestingSuiteCw20<'_> { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, } } diff --git a/packages/dao-testing/src/suite/cw4_suite.rs b/packages/dao-testing/src/suite/cw4_suite.rs index d1f9366d3..a0c5e9825 100644 --- a/packages/dao-testing/src/suite/cw4_suite.rs +++ b/packages/dao-testing/src/suite/cw4_suite.rs @@ -81,13 +81,15 @@ impl DaoTestingSuite for DaoTestingSuiteCw4<'_> { msg: to_json_binary(&dao_voting_cw4::msg::InstantiateMsg { group_contract: dao_voting_cw4::msg::GroupContract::New { cw4_group_code_id: self.cw4_group_id, + cw4_group_salt: None, initial_members: self.members.clone(), }, }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, } } diff --git a/packages/dao-testing/src/suite/cw721_suite.rs b/packages/dao-testing/src/suite/cw721_suite.rs index 311256120..9c9f7c136 100644 --- a/packages/dao-testing/src/suite/cw721_suite.rs +++ b/packages/dao-testing/src/suite/cw721_suite.rs @@ -143,6 +143,7 @@ impl DaoTestingSuite for DaoTestingSuiteCw721<'_> { msg: to_json_binary(&dao_voting_cw721_staked::msg::InstantiateMsg { nft_contract: dao_voting_cw721_staked::msg::NftContract::New { code_id: self.cw721_base_id, + salt: None, label: "voting NFT".to_string(), msg: to_json_binary(&cw721_base::msg::InstantiateMsg { name: "Voting NFT".to_string(), @@ -169,8 +170,9 @@ impl DaoTestingSuite for DaoTestingSuiteCw721<'_> { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, } } diff --git a/packages/dao-testing/src/suite/token_suite.rs b/packages/dao-testing/src/suite/token_suite.rs index 8a5f3689d..0eb135809 100644 --- a/packages/dao-testing/src/suite/token_suite.rs +++ b/packages/dao-testing/src/suite/token_suite.rs @@ -157,8 +157,9 @@ impl DaoTestingSuite for DaoTestingSuiteToken<'_> { }) .unwrap(), admin: Some(dao_interface::state::Admin::CoreModule {}), - funds: vec![], + funds: None, label: "voting module".to_string(), + salt: None, } } diff --git a/packages/dao-voting/src/pre_propose.rs b/packages/dao-voting/src/pre_propose.rs index 9384c971c..c4a75700e 100644 --- a/packages/dao-voting/src/pre_propose.rs +++ b/packages/dao-voting/src/pre_propose.rs @@ -192,8 +192,9 @@ mod tests { code_id: 42, msg: to_json_binary("foo").unwrap(), admin: None, - funds: vec![], + funds: None, label: "pre-propose-9000".to_string(), + salt: None, }, }; let (policy, messages) = info