Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: save failed submsg result in reply for timelocked contract #ntrn-80 #78

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4a733f4
feat: save execution failure for proposal in timelock contract
NeverHappened Aug 28, 2023
e3f7b16
add comment for expected format of returned error
NeverHappened Sep 1, 2023
ef65e8b
feat: save lists of failures instead of one and block height with it
NeverHappened Sep 5, 2023
0c7b849
fix lint
NeverHappened Sep 5, 2023
56765ce
review fixes
NeverHappened Sep 7, 2023
e1e145d
fix schema
NeverHappened Sep 7, 2023
5ec3ca1
add test for new code
NeverHappened Sep 7, 2023
84e1123
add failed proposal errors query to single and multiple proposals
NeverHappened Sep 13, 2023
0f08386
feat: add close_proposal_on_execution_failure logic to timelocked con…
NeverHappened Sep 13, 2023
12b92f0
add query for timelock proposal module to subdao core and use it
NeverHappened Sep 14, 2023
f9fec92
check with close_proposal_on_execution_failure = false
NeverHappened Sep 14, 2023
6ca23e0
cargo fmt and cargo schema
NeverHappened Sep 14, 2023
5f767f7
fix build
NeverHappened Sep 14, 2023
f276009
add tests for reply errors in single/multiple
NeverHappened Sep 15, 2023
f316f07
fix lint on old rust version
NeverHappened Sep 15, 2023
00089ad
Merge branch 'sdk-47' into feat/save-failed-result
NeverHappened Sep 20, 2023
03a52d1
Use just string for errors since there is only one value possible. Fi…
NeverHappened Sep 29, 2023
059fdfc
fix
NeverHappened Oct 6, 2023
71b6b2c
review fixes
NeverHappened Oct 7, 2023
8b2dda5
Get back check for subdao search
NeverHappened Oct 9, 2023
27c663f
add comment explaining subdao addr check
NeverHappened Oct 10, 2023
76304ab
review fixes - rename failed_execution_proposal_errors -> failed_prop…
NeverHappened Oct 10, 2023
6cd5624
review fixes - rename arg
NeverHappened Oct 10, 2023
381a000
timelock_contract -> Addr
NeverHappened Oct 10, 2023
61ea818
Merge branch 'sdk-47' into feat/save-failed-result
NeverHappened Oct 10, 2023
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
1 change: 1 addition & 0 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
Expand Up @@ -2557,6 +2557,30 @@
},
"additionalProperties": false
},
{
"description": "Returns errors of the failed proposal. Expected in the form of [execution_height, \"codespace=? code=?\"]. Returns `types::FailedProposalErrors`",
"type": "object",
"required": [
"proposal_failed_execution_error"
],
"properties": {
"proposal_failed_execution_error": {
"type": "object",
"required": [
"proposal_id"
],
"properties": {
"proposal_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down Expand Up @@ -6836,6 +6860,47 @@
}
}
},
"proposal_failed_execution_error": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FailedProposalErrors",
"description": "A list of proposals returned by `ProposalFailedExecutionError`.",
"type": "object",
"required": [
"errors"
],
"properties": {
"errors": {
"type": "array",
"items": {
"$ref": "#/definitions/FailedExecutionError"
}
}
},
"additionalProperties": false,
"definitions": {
"FailedExecutionError": {
"description": "Proposal failed execution error",
"type": "object",
"required": [
"error",
"height"
],
"properties": {
"error": {
"description": "Error text. Error is reduced before cosmwasm reply and is expected in form of \"codespace=? code=?\"",
"type": "string"
},
"height": {
"description": "Block height of execution error",
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
},
"proposal_hooks": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "HooksResponse",
Expand Down
24 changes: 24 additions & 0 deletions contracts/dao/proposal/cwd-proposal-multiple/schema/raw/query.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,30 @@
},
"additionalProperties": false
},
{
"description": "Returns errors of the failed proposal. Expected in the form of [execution_height, \"codespace=? code=?\"]. Returns `types::FailedProposalErrors`",
"type": "object",
"required": [
"proposal_failed_execution_error"
],
"properties": {
"proposal_failed_execution_error": {
"type": "object",
"required": [
"proposal_id"
],
"properties": {
"proposal_id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FailedProposalErrors",
"description": "A list of proposals returned by `ProposalFailedExecutionError`.",
"type": "object",
"required": [
"errors"
],
"properties": {
"errors": {
"type": "array",
"items": {
"$ref": "#/definitions/FailedExecutionError"
}
}
},
"additionalProperties": false,
"definitions": {
"FailedExecutionError": {
"description": "Proposal failed execution error",
"type": "object",
"required": [
"error",
"height"
],
"properties": {
"error": {
"description": "Error text. Error is reduced before cosmwasm reply and is expected in form of \"codespace=? code=?\"",
"type": "string"
},
"height": {
"description": "Block height of execution error",
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
}
47 changes: 43 additions & 4 deletions contracts/dao/proposal/cwd-proposal-multiple/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
to_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Reply, Response, StdResult,
Storage, SubMsg, WasmMsg,
to_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Reply, Response, StdError,
StdResult, Storage, SubMsg, WasmMsg,
};

use cw2::set_contract_version;
Expand All @@ -26,6 +26,8 @@ use cwd_voting::{
voting::{get_total_power, get_voting_power, validate_voting_period},
};

use crate::query::FailedProposalErrors;
use crate::state::{FailedExecutionError, PROPOSAL_FAILED_EXECUTION_ERRORS};
use crate::{msg::MigrateMsg, state::CREATION_POLICY};
use crate::{
msg::{ExecuteMsg, InstantiateMsg, QueryMsg},
Expand Down Expand Up @@ -730,6 +732,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
QueryMsg::ProposalHooks {} => to_binary(&PROPOSAL_HOOKS.query_hooks(deps)?),
QueryMsg::VoteHooks {} => to_binary(&VOTE_HOOKS.query_hooks(deps)?),
QueryMsg::Dao {} => query_dao(deps),
QueryMsg::ProposalFailedExecutionError { proposal_id } => {
query_proposal_failed_execution_error(deps, proposal_id)
}
}
}

Expand Down Expand Up @@ -841,8 +846,16 @@ pub fn query_info(deps: Deps) -> StdResult<Binary> {
to_binary(&cwd_interface::voting::InfoResponse { info })
}

pub fn query_proposal_failed_execution_error(deps: Deps, proposal_id: u64) -> StdResult<Binary> {
let errors = PROPOSAL_FAILED_EXECUTION_ERRORS.may_load(deps.storage, proposal_id)?;
let res = FailedProposalErrors {
errors: errors.unwrap_or_default(),
};
to_binary(&res)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result<Response, ContractError> {
pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result<Response, ContractError> {
let repl = TaggedReplyId::new(msg.id)?;
match repl {
TaggedReplyId::FailedProposalExecution(proposal_id) => {
Expand All @@ -853,7 +866,33 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result<Response, ContractE
}
None => Err(ContractError::NoSuchProposal { id: proposal_id }),
})?;
Ok(Response::new().add_attribute("proposal execution failed", proposal_id.to_string()))

// Error is reduced before cosmwasm reply and is expected in form of "codespace=? code=?"
PROPOSAL_FAILED_EXECUTION_ERRORS.update::<_, ContractError>(
deps.storage,
proposal_id,
|maybe_errors| {
let error = msg.result.into_result().err().ok_or_else(|| {
// should never happen since we reply only on failure
ContractError::Std(StdError::generic_err(
"must be an error in the failed result",
))
})?;
let value = FailedExecutionError {
height: env.block.height,
error,
};
match maybe_errors {
Some(mut errors) => {
errors.push(value);
Ok(errors)
}
None => Ok(vec![value]),
}
},
)?;

Ok(Response::new().add_attribute("proposal_execution_failed", proposal_id.to_string()))
}
TaggedReplyId::FailedProposalHook(idx) => {
let addr = PROPOSAL_HOOKS.remove_hook_by_index(deps.storage, idx)?;
Expand Down
5 changes: 5 additions & 0 deletions contracts/dao/proposal/cwd-proposal-multiple/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ pub enum QueryMsg {
/// module.
#[returns(HooksResponse)]
VoteHooks {},
/// Returns errors of the failed proposal.
/// Expected in the form of [execution_height, "codespace=? code=?"].
/// Returns `types::FailedProposalErrors`
#[returns(crate::query::FailedProposalErrors)]
ProposalFailedExecutionError { proposal_id: u64 },
}

#[cw_serde]
Expand Down
7 changes: 7 additions & 0 deletions contracts/dao/proposal/cwd-proposal-multiple/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{proposal::MultipleChoiceProposal, state::Config};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Uint128};

use crate::state::FailedExecutionError;
use cwd_voting::multiple_choice::MultipleChoiceVote;

#[cw_serde]
Expand Down Expand Up @@ -41,3 +42,9 @@ pub struct VoteListResponse {
pub struct ConfigResponse {
pub config: Config,
}

/// A list of proposals returned by `ProposalFailedExecutionError`.
#[cw_serde]
pub struct FailedProposalErrors {
pub errors: Vec<FailedExecutionError>,
}
12 changes: 12 additions & 0 deletions contracts/dao/proposal/cwd-proposal-multiple/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ pub struct Config {
pub close_proposal_on_execution_failure: bool,
}

/// Proposal failed execution error
#[cw_serde]
pub struct FailedExecutionError {
/// Block height of execution error
pub height: u64,
/// Error text. Error is reduced before cosmwasm reply and is expected in form of "codespace=? code=?"
pub error: String,
}

// we cast a ballot with our chosen vote and a given weight
// stored under the key that voted
#[cw_serde]
Expand All @@ -67,3 +76,6 @@ pub const VOTE_HOOKS: Hooks = Hooks::new("vote_hooks");
/// The address of the pre-propose module associated with this
/// proposal module (if any).
pub const CREATION_POLICY: Item<ProposalCreationPolicy> = Item::new("creation_policy");
// Execution errors for proposals that do execute only once
pub const PROPOSAL_FAILED_EXECUTION_ERRORS: Map<u64, Vec<FailedExecutionError>> =
Map::new("failed_proposal_errors");
Loading