Skip to content

Commit

Permalink
Update typos, rename some fields
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanfrey committed Dec 15, 2020
1 parent 811ca61 commit 6ab0bd7
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 79 deletions.
2 changes: 1 addition & 1 deletion contracts/cw3-fixed-multisig/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
fn query_threshold(deps: Deps) -> StdResult<ThresholdResponse> {
let cfg = CONFIG.load(deps.storage)?;
Ok(ThresholdResponse::AbsoluteCount {
weight_needed: cfg.required_weight,
weight: cfg.required_weight,
total_weight: cfg.total_weight,
})
}
Expand Down
16 changes: 8 additions & 8 deletions contracts/cw3-flex-multisig/schema/init_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"Threshold": {
"anyOf": [
{
"description": "Declares a total weight needed to pass This usually implies that count_needed is stable, even if total_weight changes eg. 3 of 5 multisig -> 3 of 6 multisig",
"description": "Declares a total weight needed to pass This usually implies that weight_needed is stable, even if total_weight changes eg. 3 of 5 multisig -> 3 of 6 multisig",
"type": "object",
"required": [
"absolute_count"
Expand All @@ -69,10 +69,10 @@
"absolute_count": {
"type": "object",
"required": [
"weight_needed"
"weight"
],
"properties": {
"weight_needed": {
"weight": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
Expand All @@ -91,18 +91,18 @@
"absolute_percentage": {
"type": "object",
"required": [
"percentage_needed"
"percentage"
],
"properties": {
"percentage_needed": {
"percentage": {
"$ref": "#/definitions/Decimal"
}
}
}
}
},
{
"description": "Declares a threshold (minimum percentage of votes that must approve) and a quorum (minimum percentage of voter weight that must vote). This allows eg. 25% of total weight YES to pass, if we have quorum of 40% and threshold of 51% and most of the people sit out the election. This is more common in general elections where participation is expected to be low.",
"description": "Declares a threshold (minimum percentage of votes that must approve) and a quorum (minimum percentage of voter weight that must vote). This allows eg. 20.04% of the total weight yes votes to pass, if we have a quorum of 40% and threshold of 51%, and most of the people sit out the election.\n\nThis is more common in general elections, where participation is expected to be low.",
"type": "object",
"required": [
"threshold_quora"
Expand All @@ -111,11 +111,11 @@
"threshold_quora": {
"type": "object",
"required": [
"quroum",
"quorum",
"threshold"
],
"properties": {
"quroum": {
"quorum": {
"$ref": "#/definitions/Decimal"
},
"threshold": {
Expand Down
18 changes: 10 additions & 8 deletions contracts/cw3-flex-multisig/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,9 @@ mod tests {
) -> (HumanAddr, HumanAddr) {
setup_test_case(
app,
Threshold::AbsoluteCount { weight_needed },
Threshold::AbsoluteCount {
weight: weight_needed,
},
max_voting_period,
init_funds,
multisig_as_group_admin,
Expand Down Expand Up @@ -610,7 +612,7 @@ mod tests {
// Zero required weight fails
let init_msg = InitMsg {
group_addr: group_addr.clone(),
threshold: Threshold::AbsoluteCount { weight_needed: 0 },
threshold: Threshold::AbsoluteCount { weight: 0 },
max_voting_period,
};
let res = app.instantiate_contract(flex_id, OWNER, &init_msg, &[], "zero required weight");
Expand All @@ -624,7 +626,7 @@ mod tests {
// Total weight less than required weight not allowed
let init_msg = InitMsg {
group_addr: group_addr.clone(),
threshold: Threshold::AbsoluteCount { weight_needed: 100 },
threshold: Threshold::AbsoluteCount { weight: 100 },
max_voting_period,
};
let res = app.instantiate_contract(flex_id, OWNER, &init_msg, &[], "high required weight");
Expand All @@ -638,7 +640,7 @@ mod tests {
// All valid
let init_msg = InitMsg {
group_addr: group_addr.clone(),
threshold: Threshold::AbsoluteCount { weight_needed: 1 },
threshold: Threshold::AbsoluteCount { weight: 1 },
max_voting_period,
};
let flex_addr = app
Expand Down Expand Up @@ -1192,7 +1194,7 @@ mod tests {
.query_wasm_smart(&flex_addr, &QueryMsg::Threshold {})
.unwrap();
let expected_thresh = ThresholdResponse::AbsoluteCount {
weight_needed: 4,
weight: 4,
total_weight: 15,
};
assert_eq!(expected_thresh, threshold);
Expand Down Expand Up @@ -1271,7 +1273,7 @@ mod tests {
.query_wasm_smart(&flex_addr, &QueryMsg::Threshold {})
.unwrap();
let expected_thresh = ThresholdResponse::AbsoluteCount {
weight_needed: 4,
weight: 4,
total_weight: 19,
};
assert_eq!(expected_thresh, threshold);
Expand Down Expand Up @@ -1396,7 +1398,7 @@ mod tests {
let (flex_addr, group_addr) = setup_test_case(
&mut app,
Threshold::AbsolutePercentage {
percentage_needed: Decimal::percent(33),
percentage: Decimal::percent(33),
},
voting_period,
coins(10, "BTC"),
Expand Down Expand Up @@ -1478,7 +1480,7 @@ mod tests {
&mut app,
Threshold::ThresholdQuora {
threshold: Decimal::percent(50),
quroum: Decimal::percent(33),
quorum: Decimal::percent(33),
},
voting_period,
coins(10, "BTC"),
Expand Down
2 changes: 1 addition & 1 deletion contracts/cw3-flex-multisig/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub enum ContractError {
#[error("Required threshold cannot be zero")]
ZeroThreshold {},

#[error("Not possible to reach required (passing) threshol")]
#[error("Not possible to reach required (passing) threshold")]
UnreachableThreshold {},

#[error("Group contract invalid address '{addr}'")]
Expand Down
82 changes: 41 additions & 41 deletions contracts/cw3-flex-multisig/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,35 @@ pub struct InitMsg {
#[serde(rename_all = "snake_case")]
pub enum Threshold {
/// Declares a total weight needed to pass
/// This usually implies that count_needed is stable, even if total_weight changes
/// This usually implies that weight_needed is stable, even if total_weight changes
/// eg. 3 of 5 multisig -> 3 of 6 multisig
AbsoluteCount { weight_needed: u64 },
AbsoluteCount { weight: u64 },
/// Declares a percentage of the total weight needed to pass
/// This implies the percentage is stable, when total_weight changes
/// eg. at 50.1%, we go from needing 51/100 to needing 101/200
///
/// Note: percentage_needed = 60% is different than threshold = 60%, quora = 100%
/// as the first will pass with 60% yes votes and 10% no votes, while the second
/// will require the others to vote anything (no, abstain...) to pass
AbsolutePercentage { percentage_needed: Decimal },
AbsolutePercentage { percentage: Decimal },
/// Declares a threshold (minimum percentage of votes that must approve)
/// and a quorum (minimum percentage of voter weight that must vote).
/// This allows eg. 25% of total weight YES to pass, if we have quorum of 40%
/// and threshold of 51% and most of the people sit out the election.
/// This is more common in general elections where participation is expected
/// This allows eg. 20.04% of the total weight yes votes to pass, if we have
/// a quorum of 40% and threshold of 51%, and most of the people sit out the election.
///
/// This is more common in general elections, where participation is expected
/// to be low.
ThresholdQuora { threshold: Decimal, quroum: Decimal },
ThresholdQuora { threshold: Decimal, quorum: Decimal },
}

impl Threshold {
/// returns error if this is an unreachable value,
/// given a total weight of all members in the group
pub fn validate(&self, total_weight: u64) -> Result<(), ContractError> {
match self {
Threshold::AbsoluteCount { weight_needed } => {
Threshold::AbsoluteCount {
weight: weight_needed,
} => {
if *weight_needed == 0 {
Err(ContractError::ZeroThreshold {})
} else if *weight_needed > total_weight {
Expand All @@ -53,10 +56,13 @@ impl Threshold {
Ok(())
}
}
Threshold::AbsolutePercentage { percentage_needed } => {
valid_percentage(percentage_needed)
}
Threshold::ThresholdQuora { threshold, quroum } => {
Threshold::AbsolutePercentage {
percentage: percentage_needed,
} => valid_percentage(percentage_needed),
Threshold::ThresholdQuora {
threshold,
quorum: quroum,
} => {
valid_percentage(threshold)?;
valid_percentage(quroum)
}
Expand All @@ -66,19 +72,17 @@ impl Threshold {
/// Creates a response from the saved data, just missing the total_weight info
pub fn to_response(&self, total_weight: u64) -> ThresholdResponse {
match self.clone() {
Threshold::AbsoluteCount { weight_needed } => ThresholdResponse::AbsoluteCount {
weight_needed,
Threshold::AbsoluteCount { weight } => ThresholdResponse::AbsoluteCount {
weight,
total_weight,
},
Threshold::AbsolutePercentage { percentage_needed } => {
ThresholdResponse::AbsolutePercentage {
percentage_needed,
total_weight,
}
}
Threshold::ThresholdQuora { threshold, quroum } => ThresholdResponse::ThresholdQuora {
Threshold::AbsolutePercentage { percentage } => ThresholdResponse::AbsolutePercentage {
percentage,
total_weight,
},
Threshold::ThresholdQuora { threshold, quorum } => ThresholdResponse::ThresholdQuora {
threshold,
quroum,
quorum,
total_weight,
},
}
Expand Down Expand Up @@ -193,49 +197,45 @@ mod tests {
#[test]
fn validate_threshold() {
// absolute count ensures 0 < required <= total_weight
let err = Threshold::AbsoluteCount { weight_needed: 0 }
let err = Threshold::AbsoluteCount { weight: 0 }
.validate(5)
.unwrap_err();
// TODO: remove to_string() when PartialEq implemented
assert_eq!(err.to_string(), ContractError::ZeroThreshold {}.to_string());
let err = Threshold::AbsoluteCount { weight_needed: 6 }
let err = Threshold::AbsoluteCount { weight: 6 }
.validate(5)
.unwrap_err();
assert_eq!(
err.to_string(),
ContractError::UnreachableThreshold {}.to_string()
);

Threshold::AbsoluteCount { weight_needed: 1 }
.validate(5)
.unwrap();
Threshold::AbsoluteCount { weight_needed: 5 }
.validate(5)
.unwrap();
Threshold::AbsoluteCount { weight: 1 }.validate(5).unwrap();
Threshold::AbsoluteCount { weight: 5 }.validate(5).unwrap();

// AbsolutePercentage just enforces valid_percentage (tested above)
let err = Threshold::AbsolutePercentage {
percentage_needed: Decimal::zero(),
percentage: Decimal::zero(),
}
.validate(5)
.unwrap_err();
assert_eq!(err.to_string(), ContractError::ZeroThreshold {}.to_string());
Threshold::AbsolutePercentage {
percentage_needed: Decimal::percent(51),
percentage: Decimal::percent(51),
}
.validate(5)
.unwrap();

// Quorum enforces both valid just enforces valid_percentage (tested above)
Threshold::ThresholdQuora {
threshold: Decimal::percent(51),
quroum: Decimal::percent(40),
quorum: Decimal::percent(40),
}
.validate(5)
.unwrap();
let err = Threshold::ThresholdQuora {
threshold: Decimal::percent(101),
quroum: Decimal::percent(40),
quorum: Decimal::percent(40),
}
.validate(5)
.unwrap_err();
Expand All @@ -245,7 +245,7 @@ mod tests {
);
let err = Threshold::ThresholdQuora {
threshold: Decimal::percent(51),
quroum: Decimal::percent(0),
quorum: Decimal::percent(0),
}
.validate(5)
.unwrap_err();
Expand All @@ -256,37 +256,37 @@ mod tests {
fn threshold_response() {
let total_weight: u64 = 100;

let res = Threshold::AbsoluteCount { weight_needed: 42 }.to_response(total_weight);
let res = Threshold::AbsoluteCount { weight: 42 }.to_response(total_weight);
assert_eq!(
res,
ThresholdResponse::AbsoluteCount {
weight_needed: 42,
weight: 42,
total_weight
}
);

let res = Threshold::AbsolutePercentage {
percentage_needed: Decimal::percent(51),
percentage: Decimal::percent(51),
}
.to_response(total_weight);
assert_eq!(
res,
ThresholdResponse::AbsolutePercentage {
percentage_needed: Decimal::percent(51),
percentage: Decimal::percent(51),
total_weight
}
);

let res = Threshold::ThresholdQuora {
threshold: Decimal::percent(66),
quroum: Decimal::percent(50),
quorum: Decimal::percent(50),
}
.to_response(total_weight);
assert_eq!(
res,
ThresholdResponse::ThresholdQuora {
threshold: Decimal::percent(66),
quroum: Decimal::percent(50),
quorum: Decimal::percent(50),
total_weight
}
);
Expand Down
21 changes: 13 additions & 8 deletions contracts/cw3-flex-multisig/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,16 @@ impl Proposal {
// sequence of possible votes can cause it to fail)
pub fn is_passed(&self, block: &BlockInfo) -> bool {
match self.threshold {
Threshold::AbsoluteCount { weight_needed } => self.votes.yes >= weight_needed,
Threshold::AbsolutePercentage { percentage_needed } => {
self.votes.yes >= votes_needed(self.total_weight, percentage_needed)
}
Threshold::ThresholdQuora { threshold, quroum } => {
Threshold::AbsoluteCount {
weight: weight_needed,
} => self.votes.yes >= weight_needed,
Threshold::AbsolutePercentage {
percentage: percentage_needed,
} => self.votes.yes >= votes_needed(self.total_weight, percentage_needed),
Threshold::ThresholdQuora {
threshold,
quorum: quroum,
} => {
// this one is tricky, as we have two compares:
if self.expires.is_expired(block) {
// * if we have closed yet, we need quorum% of total votes to have voted (counting abstain)
Expand Down Expand Up @@ -227,7 +232,7 @@ mod test {

#[test]
fn proposal_passed_absolute_count() {
let fixed = Threshold::AbsoluteCount { weight_needed: 10 };
let fixed = Threshold::AbsoluteCount { weight: 10 };
let mut votes = Votes::new(7);
votes.add_vote(Vote::Veto, 4);
// same expired or not, total_weight or whatever
Expand All @@ -254,7 +259,7 @@ mod test {
#[test]
fn proposal_passed_absolute_percentage() {
let percent = Threshold::AbsolutePercentage {
percentage_needed: Decimal::percent(50),
percentage: Decimal::percent(50),
};
let mut votes = Votes::new(7);
votes.add_vote(Vote::No, 4);
Expand Down Expand Up @@ -284,7 +289,7 @@ mod test {
fn proposal_passed_quorum() {
let quorum = Threshold::ThresholdQuora {
threshold: Decimal::percent(50),
quroum: Decimal::percent(40),
quorum: Decimal::percent(40),
};
// all non-yes votes are counted for quorum
let passing = Votes {
Expand Down
Loading

0 comments on commit 6ab0bd7

Please sign in to comment.