Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 19 additions & 22 deletions contracts/cw3-fixed-multisig/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use cw3::{
ProposalListResponse, ProposalResponse, Status, ThresholdResponse, Vote, VoteInfo,
VoteListResponse, VoteResponse, VoterDetail, VoterListResponse, VoterResponse,
};
use cw_storage_plus::{AddrRef, Bound};
use cw_storage_plus::Bound;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
Expand Down Expand Up @@ -56,7 +56,7 @@ pub fn instantiate(
// add all voters
for voter in msg.voters.iter() {
let key = deps.api.addr_validate(&voter.addr)?;
VOTERS.save(deps.storage, AddrRef::new(&key), &voter.weight)?;
VOTERS.save(deps.storage, &key, &voter.weight)?;
}
Ok(Response::default())
}
Expand Down Expand Up @@ -92,9 +92,8 @@ pub fn execute_propose(
latest: Option<Expiration>,
) -> Result<Response<Empty>, ContractError> {
// only members of the multisig can create a proposal
let sender = AddrRef::new(&info.sender);
let vote_power = VOTERS
.may_load(deps.storage, sender)?
.may_load(deps.storage, &info.sender)?
.ok_or(ContractError::Unauthorized {})?;

let cfg = CONFIG.load(deps.storage)?;
Expand Down Expand Up @@ -126,14 +125,14 @@ pub fn execute_propose(
required_weight: cfg.required_weight,
};
let id = next_id(deps.storage)?;
PROPOSALS.save(deps.storage, id.into(), &prop)?;
PROPOSALS.save(deps.storage, &id.into(), &prop)?;

// add the first yes vote from voter
let ballot = Ballot {
weight: vote_power,
vote: Vote::Yes,
};
BALLOTS.save(deps.storage, (id.into(), sender), &ballot)?;
BALLOTS.save(deps.storage, &(id.into(), info.sender.clone()), &ballot)?;

Ok(Response {
submessages: vec![],
Expand All @@ -156,13 +155,12 @@ pub fn execute_vote(
vote: Vote,
) -> Result<Response<Empty>, ContractError> {
// only members of the multisig can vote
let sender = AddrRef::new(&info.sender);
let vote_power = VOTERS
.may_load(deps.storage, sender)?
.may_load(deps.storage, &info.sender)?
.ok_or(ContractError::Unauthorized {})?;

// ensure proposal exists and can be voted on
let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?;
let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?;
if prop.status != Status::Open {
return Err(ContractError::NotOpen {});
}
Expand All @@ -173,7 +171,7 @@ pub fn execute_vote(
// cast vote if no vote previously cast
BALLOTS.update(
deps.storage,
(proposal_id.into(), sender),
&(proposal_id.into(), info.sender.clone()),
|bal| match bal {
Some(_) => Err(ContractError::AlreadyVoted {}),
None => Ok(Ballot {
Expand All @@ -190,7 +188,7 @@ pub fn execute_vote(
if prop.yes_weight >= prop.required_weight {
prop.status = Status::Passed;
}
PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?;
PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?;
}

Ok(Response {
Expand All @@ -214,7 +212,7 @@ pub fn execute_execute(
) -> Result<Response, ContractError> {
// anyone can trigger this if the vote passed

let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?;
let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?;
// we allow execution even after the proposal "expiration" as long as all vote come in before
// that point. If it was approved on time, it can be executed any time.
if prop.status != Status::Passed {
Expand All @@ -223,7 +221,7 @@ pub fn execute_execute(

// set it to executed
prop.status = Status::Executed;
PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?;
PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?;

// dispatch all proposed messages
Ok(Response {
Expand All @@ -246,7 +244,7 @@ pub fn execute_close(
) -> Result<Response<Empty>, ContractError> {
// anyone can trigger this if the vote passed

let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?;
let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?;
if [Status::Executed, Status::Rejected, Status::Passed]
.iter()
.any(|x| *x == prop.status)
Expand All @@ -259,7 +257,7 @@ pub fn execute_close(

// set it to failed
prop.status = Status::Rejected;
PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?;
PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?;

Ok(Response {
submessages: vec![],
Expand Down Expand Up @@ -307,7 +305,7 @@ fn query_threshold(deps: Deps) -> StdResult<ThresholdResponse> {
}

fn query_proposal(deps: Deps, env: Env, id: u64) -> StdResult<ProposalResponse> {
let prop = PROPOSALS.load(deps.storage, id.into())?;
let prop = PROPOSALS.load(deps.storage, &id.into())?;
let status = prop.current_status(&env.block);

let cfg = CONFIG.load(deps.storage)?;
Expand Down Expand Up @@ -395,12 +393,10 @@ fn map_proposal(
}

fn query_vote(deps: Deps, proposal_id: u64, voter: String) -> StdResult<VoteResponse> {
let ballot = BALLOTS.may_load(
deps.storage,
(proposal_id.into(), AddrRef::unchecked(&voter)),
)?;
let voter = deps.api.addr_validate(&voter)?;
let ballot = BALLOTS.may_load(deps.storage, &(proposal_id.into(), voter.clone()))?;
let vote = ballot.map(|b| VoteInfo {
voter,
voter: voter.into(),
vote: b.vote,
weight: b.weight,
});
Expand Down Expand Up @@ -434,7 +430,8 @@ fn list_votes(
}

fn query_voter(deps: Deps, voter: String) -> StdResult<VoterResponse> {
let weight = VOTERS.may_load(deps.storage, AddrRef::unchecked(&voter))?;
let voter = deps.api.addr_validate(&voter)?;
let weight = VOTERS.may_load(deps.storage, &voter)?;
Ok(VoterResponse { weight })
}

Expand Down
8 changes: 4 additions & 4 deletions contracts/cw3-fixed-multisig/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;

use cosmwasm_std::{BlockInfo, CosmosMsg, Empty, StdError, StdResult, Storage};
use cosmwasm_std::{Addr, BlockInfo, CosmosMsg, Empty, StdError, StdResult, Storage};

use cw0::{Duration, Expiration};
use cw3::{Status, Vote};
use cw_storage_plus::{AddrRef, Item, Map, U64Key};
use cw_storage_plus::{Item, Map, U64Key};

#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Config {
Expand Down Expand Up @@ -57,9 +57,9 @@ pub const CONFIG: Item<Config> = Item::new("config");
pub const PROPOSAL_COUNT: Item<u64> = Item::new("proposal_count");

// multiple-item maps
pub const VOTERS: Map<AddrRef, u64> = Map::new("voters");
pub const VOTERS: Map<Addr, u64> = Map::new("voters");
pub const PROPOSALS: Map<U64Key, Proposal> = Map::new("proposals");
pub const BALLOTS: Map<(U64Key, AddrRef), Ballot> = Map::new("ballots");
pub const BALLOTS: Map<(U64Key, Addr), Ballot> = Map::new("ballots");

pub fn next_id(store: &mut dyn Storage) -> StdResult<u64> {
let id: u64 = PROPOSAL_COUNT.may_load(store)?.unwrap_or_default() + 1;
Expand Down
Loading