Repository: DA0-DA0/dao-contracts
Pull request #215 (2022-03-23 18:50:51)

Fixed staked token creation without any initial non-DAO owners
Fix oversight in previous PR #212 


Patch:
diff --git a/contracts/cw-governance/src/helpers.rs b/contracts/cw-governance/src/helpers.rs
index 72102892..05d4002e 100644
--- a/contracts/cw-governance/src/helpers.rs
+++ b/contracts/cw-governance/src/helpers.rs
@@ -8,7 +8,7 @@ impl ModuleInstantiateInfo {
             admin: match self.admin {
                 Admin::Address { addr } => Some(addr),
                 Admin::GovernanceContract {} => Some(contract_address.to_string()),
-                Admin::None {} => None,
+                Admin::None => None,
             },
             code_id: self.code_id,
             msg: self.msg,
diff --git a/contracts/cw-governance/src/msg.rs b/contracts/cw-governance/src/msg.rs
index 1b89d96b..f33715a7 100644
--- a/contracts/cw-governance/src/msg.rs
+++ b/contracts/cw-governance/src/msg.rs
@@ -16,7 +16,7 @@ pub enum Admin {
     /// while instantiation takes place.
     GovernanceContract {},
     /// No admin.
-    None {},
+    None,
 }
 
 /// Information needed to instantiate a governance or voting module.
diff --git a/contracts/cw-govmod-single/src/msg.rs b/contracts/cw-govmod-single/src/msg.rs
index 2cbf45a5..03284f65 100644
--- a/contracts/cw-govmod-single/src/msg.rs
+++ b/contracts/cw-govmod-single/src/msg.rs
@@ -28,14 +28,14 @@ pub struct InstantiateMsg {
 #[serde(rename_all = "snake_case")]
 pub enum DepositToken {
     /// Use a specific token address as the deposit token.
-    Token { address: String },
+    Token(String),
     /// Use the token address of the associated DAO's voting
     /// module. NOTE: in order to use the token address of the voting
     /// module the voting module must (1) use a cw20 token and (2)
     /// implement the `TokenContract {}` query type defined by
     /// `cw_governance_macros::token_query`. Failing to implement that
     /// and using this option will cause instantiation to fail.
-    VotingModuleToken {},
+    VotingModuleToken,
 }
 
 /// Information about the deposit required to create a proposal.
diff --git a/contracts/cw-govmod-single/src/state.rs b/contracts/cw-govmod-single/src/state.rs
index 83e0cfc6..19d5ce7a 100644
--- a/contracts/cw-govmod-single/src/state.rs
+++ b/contracts/cw-govmod-single/src/state.rs
@@ -67,8 +67,8 @@ impl DepositInfo {
             refund_failed_proposals,
         } = self;
         let token = match token {
-            DepositToken::Token { address } => deps.api.addr_validate(&address)?,
-            DepositToken::VotingModuleToken {} => {
+            DepositToken::Token(token) => deps.api.addr_validate(&token)?,
+            DepositToken::VotingModuleToken => {
                 let voting_module: Addr = deps
                     .querier
                     .query_wasm_smart(dao, &cw_governance::msg::QueryMsg::VotingModule {})?;
diff --git a/contracts/cw20-staked-balance-voting/src/contract.rs b/contracts/cw20-staked-balance-voting/src/contract.rs
index 6b926572..bbafdda7 100644
--- a/contracts/cw20-staked-balance-voting/src/contract.rs
+++ b/contracts/cw20-staked-balance-voting/src/contract.rs
@@ -95,6 +95,14 @@ pub fn instantiate(
             staking_code_id,
             unstaking_duration,
         } => {
+            let initial_supply = initial_balances
+                .iter()
+                .fold(Uint128::zero(), |p, n| p + n.amount);
+            // Cannot instantiate with no initial token owners because it would immediately lock the DAO.
+            if initial_supply.is_zero() {
+                return Err(ContractError::InitialBalancesError {});
+            }
+
             // Add DAO initial balance to initial_balances vector if defined.
             if let Some(initial_dao_balance) = msg.initial_dao_balance {
                 if initial_dao_balance > Uint128::zero() {
@@ -105,13 +113,6 @@ pub fn instantiate(
                 }
             }
 
-            let initial_supply = initial_balances
-                .iter()
-                .fold(Uint128::zero(), |p, n| p + n.amount);
-            if initial_supply.is_zero() {
-                return Err(ContractError::InitialBalancesError {});
-            }
-
             STAKING_CONTRACT_CODE_ID.save(deps.storage, &staking_code_id)?;
             STAKING_CONTRACT_UNSTAKING_DURATION.save(deps.storage, &unstaking_duration)?;
 


Test patch:
diff --git a/contracts/cw-govmod-single/src/tests.rs b/contracts/cw-govmod-single/src/tests.rs
index baa8d971..3afd4f25 100644
--- a/contracts/cw-govmod-single/src/tests.rs
+++ b/contracts/cw-govmod-single/src/tests.rs
@@ -753,7 +753,7 @@ fn test_voting_module_token_proposal_deposit_instantiate() {
         max_voting_period,
         only_members_execute: false,
         deposit_info: Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -828,9 +828,7 @@ fn test_different_token_proposal_deposit() {
         max_voting_period,
         only_members_execute: false,
         deposit_info: Some(DepositInfo {
-            token: DepositToken::Token {
-                address: cw20_addr.to_string(),
-            },
+            token: DepositToken::Token(cw20_addr.to_string()),
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -883,9 +881,7 @@ fn test_bad_token_proposal_deposit() {
         max_voting_period,
         only_members_execute: false,
         deposit_info: Some(DepositInfo {
-            token: DepositToken::Token {
-                address: votemod_addr.to_string(),
-            },
+            token: DepositToken::Token(votemod_addr.to_string()),
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -908,7 +904,7 @@ fn test_take_proposal_deposit() {
         max_voting_period,
         only_members_execute: false,
         deposit_info: Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -1018,7 +1014,7 @@ fn test_deposit_return_on_execute() {
         Status::Passed,
         None,
         Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: false,
         }),
@@ -1090,7 +1086,7 @@ fn test_close_open_proposal() {
         Status::Open,
         Some(Uint128::new(100)),
         Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -1164,7 +1160,7 @@ fn test_deposit_return_on_close() {
         Status::Rejected,
         None,
         Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: true,
         }),
@@ -1236,7 +1232,7 @@ fn test_no_return_if_no_refunds() {
         Status::Rejected,
         None,
         Some(DepositInfo {
-            token: DepositToken::VotingModuleToken {},
+            token: DepositToken::VotingModuleToken,
             deposit: Uint128::new(1),
             refund_failed_proposals: false,
         }),