Skip to content

Commit

Permalink
revert v2 migration on prop-single
Browse files Browse the repository at this point in the history
  • Loading branch information
bekauz committed Dec 1, 2023
1 parent 71ae2b9 commit ede9401
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 449 deletions.
11 changes: 4 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ test-context = "0.1"
thiserror = {version = "1.0"}
token-bindings = "0.11.0"
wynd-utils = "0.4"
semver = "1"

# One commit ahead of version 0.3.0. Allows initialization with an
# optional owner.
Expand Down Expand Up @@ -128,10 +127,12 @@ cw4-voting-v1 = { package = "cw4-voting", version = "0.1.0" }
voting-v1 = { package = "dao-voting", version = "0.1.0" }
stake-cw20-v03 = { package = "stake-cw20", version = "0.2.6" }


# v2 dependencies. used for state migrations
cw-utils-v2 = { package = "cw-utils", version = "0.16" }
dao-dao-core-v2 = { package = "dao-dao-core", version = "2.2.0" }
dao-interface-v2 = { package = "dao-interface", version = "2.2.0" }
dao-proposal-single-v2 = { package = "dao-proposal-single", version = "2.2.0" }
dao-pre-propose-single-v2 = { package = "dao-pre-propose-single", version = "2.2.0" }
voting-v2 = { package = "dao-voting", version = "2.2.0" }
voting-v2 = { package = "dao-voting", version = "2.2.0"}

16 changes: 4 additions & 12 deletions contracts/proposal/dao-proposal-single/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,9 @@ dao-voting = { workspace = true }
cw-hooks = { workspace = true }
dao-hooks = { workspace = true }

# Deps required for v2 migration
cw-utils-v2 = { workspace = true }
voting-v2 = { workspace = true }
dao-proposal-single-v2 = { workspace = true, features = ["library"] }

# deps for v3 migration
semver = { workspace = true, features = [] }
cw-utils-v1 = { workspace = true}
voting-v1 = { workspace = true }
cw-proposal-single-v1 = { workspace = true, features = ["library"] }

[dev-dependencies]
cosmwasm-schema = { workspace = true }
Expand All @@ -59,8 +55,4 @@ cw20-base = { workspace = true }
cw721-base = { workspace = true }
cw4 = { workspace = true }
cw4-group = { workspace = true }

# Required for migration testing
dao-dao-core-v2 = { workspace = true, features = ["library"] }
dao-interface-v2 = { workspace = true }
dao-pre-propose-single-v2 = { workspace = true, features = ["library"] }
cw-core-v1 = { workspace = true, features = ["library"] }
83 changes: 41 additions & 42 deletions contracts/proposal/dao-proposal-single/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@ use dao_voting::status::Status;
use dao_voting::threshold::Threshold;
use dao_voting::veto::{VetoConfig, VetoError};
use dao_voting::voting::{get_total_power, get_voting_power, validate_voting_period, Vote, Votes};
use semver::Version;
use std::str::FromStr;

use crate::msg::MigrateMsg;
use crate::proposal::{next_proposal_id, SingleChoiceProposal};
use crate::state::{Config, CREATION_POLICY};

use crate::v2_state::{v2_status_to_v3, v2_threshold_to_v3, v2_votes_to_v3};
use cw_proposal_single_v1 as v1;
use crate::{
error::ContractError,
msg::{ExecuteMsg, InstantiateMsg, QueryMsg},
Expand All @@ -40,7 +37,9 @@ use crate::{
query::{ProposalResponse, VoteInfo, VoteListResponse, VoteResponse},
state::{Ballot, BALLOTS, CONFIG, PROPOSALS, PROPOSAL_COUNT, PROPOSAL_HOOKS, VOTE_HOOKS},
};

use crate::v1_state::{
v1_duration_to_v2, v1_expiration_to_v2, v1_status_to_v2, v1_threshold_to_v2, v1_votes_to_v2,
};
pub(crate) const CONTRACT_NAME: &str = "crates.io:dao-proposal-single";
pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

Expand Down Expand Up @@ -952,58 +951,58 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, Co
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

match msg {
MigrateMsg::FromV2 { veto } => {
let version_2 = Version::new(2, 0, 0);

MigrateMsg::FromV1 {
close_proposal_on_execution_failure,
pre_propose_info,
veto
} => {
// `CONTRACT_VERSION` here is from the data section of the
// blob we are migrating to. `version` is from storage.
let target_blob_version = Version::from_str(CONTRACT_VERSION)
.map_err(|_| ContractError::MigrationVersionError {})?;
let parsed_version =
Version::from_str(&version).map_err(|_| ContractError::MigrationVersionError {})?;

// If the version in storage matches the version in the blob
// blob we are migrating to. `version` is from storage. If
// the version in storage matches the version in the blob
// we are not upgrading.
if parsed_version == target_blob_version {
if version == CONTRACT_VERSION {
return Err(ContractError::AlreadyMigrated {});
}

// migration is only possible from 2.0.0, but no later than the
// version of the blob we are migrating to
if parsed_version < version_2 || parsed_version > target_blob_version {
return Err(ContractError::MigrationVersionError {});
}

// Update the stored config to have the new `veto` field
let current_config = dao_proposal_single_v2::state::CONFIG.load(deps.storage)?;
// Update the stored config to have the new
// `close_proposal_on_execution_failure` field.
let current_config = v1::state::CONFIG.load(deps.storage)?;
CONFIG.save(
deps.storage,
&Config {
threshold: v2_threshold_to_v3(current_config.threshold),
max_voting_period: current_config.max_voting_period,
min_voting_period: current_config.min_voting_period,
threshold: v1_threshold_to_v2(current_config.threshold),
max_voting_period: v1_duration_to_v2(current_config.max_voting_period),
min_voting_period: current_config.min_voting_period.map(v1_duration_to_v2),
only_members_execute: current_config.only_members_execute,
allow_revoting: current_config.allow_revoting,
dao: current_config.dao.clone(),
close_proposal_on_execution_failure: current_config
.close_proposal_on_execution_failure,
close_proposal_on_execution_failure,
veto,
},
)?;

// Update the module's proposals to v3.
let current_proposals = dao_proposal_single_v2::state::PROPOSALS
let (initial_policy, pre_propose_messages) =
pre_propose_info.into_initial_policy_and_messages(current_config.dao)?;
CREATION_POLICY.save(deps.storage, &initial_policy)?;

// Update the module's proposals to v2.

let current_proposals = v1::state::PROPOSALS
.range(deps.storage, None, None, Order::Ascending)
.collect::<StdResult<Vec<(u64, dao_proposal_single_v2::proposal::SingleChoiceProposal)>>>()?;
.collect::<StdResult<Vec<(u64, v1::proposal::Proposal)>>>()?;

// Based on gas usage testing, we estimate that we will be
// able to migrate ~4200 proposals at a time before
// reaching the block max_gas limit.
current_proposals
.into_iter()
.try_for_each::<_, Result<_, ContractError>>(|(id, prop)| {
if prop.status != voting_v2::status::Status::Closed
&& prop.status != voting_v2::status::Status::Executed
if prop
.deposit_info
.map(|info| !info.deposit.is_zero())
.unwrap_or(false)
&& prop.status != voting_v1::Status::Closed
&& prop.status != voting_v1::Status::Executed
{
// No migration path for outstanding
// deposits.
Expand All @@ -1015,13 +1014,13 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, Co
description: prop.description,
proposer: prop.proposer,
start_height: prop.start_height,
min_voting_period: prop.min_voting_period,
expiration: prop.expiration,
threshold: v2_threshold_to_v3(prop.threshold),
min_voting_period: prop.min_voting_period.map(v1_expiration_to_v2),
expiration: v1_expiration_to_v2(prop.expiration),
threshold: v1_threshold_to_v2(prop.threshold),
total_power: prop.total_power,
msgs: prop.msgs,
status: v2_status_to_v3(prop.status),
votes: v2_votes_to_v3(prop.votes),
status: v1_status_to_v2(prop.status),
votes: v1_votes_to_v2(prop.votes),
allow_revoting: prop.allow_revoting,
veto: None,
};
Expand All @@ -1033,9 +1032,9 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, Co

Ok(Response::default()
.add_attribute("action", "migrate")
.add_attribute("from", "v2"))
}

.add_attribute("from", "v1")
.add_submessages(pre_propose_messages))
},
MigrateMsg::FromCompatible {} => Ok(Response::default()
.add_attribute("action", "migrate")
.add_attribute("from", "compatible")),
Expand Down
2 changes: 1 addition & 1 deletion contracts/proposal/dao-proposal-single/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ pub mod query;
mod testing;

pub mod state;
mod v2_state;
pub mod v1_state;

pub use crate::error::ContractError;
21 changes: 20 additions & 1 deletion contracts/proposal/dao-proposal-single/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,26 @@ pub enum QueryMsg {

#[cw_serde]
pub enum MigrateMsg {
FromV2 {
FromV1 {
/// This field was not present in DAO DAO v1. To migrate, a
/// value must be specified.
///
/// If set to true proposals will be closed if their execution
/// fails. Otherwise, proposals will remain open after execution
/// failure. For example, with this enabled a proposal to send 5
/// tokens out of a DAO's treasury with 4 tokens would be closed when
/// it is executed. With this disabled, that same proposal would
/// remain open until the DAO's treasury was large enough for it to be
/// executed.
close_proposal_on_execution_failure: bool,
/// This field was not present in DAO DAO v1. To migrate, a
/// value must be specified.
///
/// This contains information about how a pre-propose module may be configured.
/// If set to "AnyoneMayPropose", there will be no pre-propose module and consequently,
/// no deposit or membership checks when submitting a proposal. The "ModuleMayPropose"
/// option allows for instantiating a prepropose module which will handle deposit verification and return logic.
pre_propose_info: PreProposeInfo,
/// This field was not present in DAO DAO v2. To migrate, a
/// value must be specified.
///
Expand Down
Loading

0 comments on commit ede9401

Please sign in to comment.