Skip to content
Draft
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
17 changes: 14 additions & 3 deletions contracts/treasury/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,24 @@ pub fn execute(
#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GrantConfigByTypeUrl { msg_type_url } => to_json_binary(
&query::grant_config_by_type_url(deps.storage, msg_type_url)?,
QueryMsg::RawGrantConfigByTypeUrl { msg_type_url } => to_json_binary(
&query::raw_grant_config_by_type_url(deps.storage, msg_type_url)?,
),
QueryMsg::GrantConfigByTypeUrl {
msg_type_url,
account_address,
} => to_json_binary(&query::grant_config_by_type_url(
deps.storage,
msg_type_url,
account_address,
)?),
QueryMsg::GrantConfigTypeUrls {} => {
to_json_binary(&query::grant_config_type_urls(deps.storage)?)
}
QueryMsg::FeeConfig {} => to_json_binary(&query::fee_config(deps.storage)?),
QueryMsg::FeeConfig { address } => {
to_json_binary(&query::fee_config(deps.storage, address)?)
}
QueryMsg::RawFeeConfig {} => to_json_binary(&query::raw_fee_config(deps.storage)?),
QueryMsg::Admin {} => to_json_binary(&query::admin(deps.storage)?),
QueryMsg::PendingAdmin {} => to_json_binary(&query::pending_admin(deps.storage)?),
QueryMsg::Params {} => to_json_binary(&query::params(deps.storage)?),
Expand Down
11 changes: 11 additions & 0 deletions contracts/treasury/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use cosmwasm_std::StdError;

#[derive(Debug, thiserror::Error)]
pub enum ContractError {
#[error(transparent)]
Expand Down Expand Up @@ -38,3 +40,12 @@ pub enum ContractError {
}

pub type ContractResult<T> = Result<T, ContractError>;

impl From<ContractError> for StdError {
fn from(val: ContractError) -> Self {
match val {
ContractError::Std(err) => err,
_ => StdError::generic_err(val.to_string()),
}
}
}
24 changes: 17 additions & 7 deletions contracts/treasury/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::error::ContractError::{
};
use crate::error::ContractResult;
use crate::grant::allowance::format_allowance;
use crate::grant::{FeeConfig, GrantConfig};
use crate::grant::{FeeConfigStorage, GrantConfigStorage};
use crate::state::{Params, ADMIN, FEE_CONFIG, GRANT_CONFIGS, PARAMS, PENDING_ADMIN};
use cosmos_sdk_proto::cosmos::authz::v1beta1::{QueryGrantsRequest, QueryGrantsResponse};
use cosmos_sdk_proto::cosmos::feegrant::v1beta1::QueryAllowanceRequest;
Expand All @@ -22,8 +22,8 @@ pub fn init(
info: MessageInfo,
admin: Option<Addr>,
type_urls: Vec<String>,
grant_configs: Vec<GrantConfig>,
fee_config: FeeConfig,
grant_configs: Vec<GrantConfigStorage>,
fee_config: FeeConfigStorage,
) -> ContractResult<Response> {
let treasury_admin = match admin {
None => info.sender,
Expand Down Expand Up @@ -116,7 +116,7 @@ pub fn update_grant_config(
deps: DepsMut,
info: MessageInfo,
msg_type_url: String,
grant_config: GrantConfig,
grant_config: GrantConfigStorage,
) -> ContractResult<Response> {
let admin = ADMIN.load(deps.storage)?;
if admin != info.sender {
Expand Down Expand Up @@ -165,7 +165,7 @@ pub fn remove_grant_config(
pub fn update_fee_config(
deps: DepsMut,
info: MessageInfo,
fee_config: FeeConfig,
fee_config: FeeConfigStorage,
) -> ContractResult<Response> {
let admin = ADMIN.load(deps.storage)?;
if admin != info.sender {
Expand Down Expand Up @@ -246,7 +246,12 @@ pub fn deploy_fee_grant(
None => return Err(AuthzGrantNotFound { msg_type_url }),
Some(auth) => {
// the authorization must match the one in the config
if grant_config.authorization.ne(&auth.into()) {
// Here authz_granter is supposed to be the abstract account (giving permissions)
if grant_config
.try_into_grant_config(authz_granter.to_string())?
.authorization
.ne(&auth.into())
{
return Err(AuthzGrantMismatch);
}
}
Expand All @@ -259,7 +264,12 @@ pub fn deploy_fee_grant(

let fee_config = FEE_CONFIG.load(deps.storage)?;
// create feegrant, if needed
match fee_config.allowance {
// Here authz_granter is supposed to be the abstract account (giving authz permissions)
match fee_config
.allowance
.map(|a| a.try_into_any(authz_granter.to_string()))
.transpose()?
{
// this treasury doesn't deploy any fees, and can return
None => Ok(Response::new()),
// allowance should be stored as a prost proto from the feegrant definition
Expand Down
110 changes: 110 additions & 0 deletions contracts/treasury/src/grant.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,132 @@
pub mod allowance;

use cosmos_sdk_proto::{prost::Name, traits::MessageExt};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Binary;

use crate::error::ContractResult;

#[cw_serde]
pub struct GrantConfig {
description: String,
pub authorization: Any,
pub optional: bool,
}

#[cw_serde]

pub enum AuthorizationData {
Any(Any),
ExecuteOnAccount(AuthorizationOnAccount),
}

#[cw_serde]

pub struct AuthorizationOnAccount {
pub limit: Option<Any>,
pub filter: Option<Any>,
}

#[cw_serde]

pub struct GrantConfigStorage {
pub description: String,
pub authorization: AuthorizationData,
pub optional: bool,
}

impl AuthorizationData {
pub fn try_into_any(self, address: String) -> ContractResult<Any> {
Ok(match self {
AuthorizationData::Any(any) => any,
AuthorizationData::ExecuteOnAccount(auth) => {
// Handle the case where authorization is on the account itself
Any {
type_url: cosmos_sdk_proto::cosmwasm::wasm::v1::ContractExecutionAuthorization::full_name(),
value:
cosmos_sdk_proto::cosmwasm::wasm::v1::ContractExecutionAuthorization {
grants: vec![cosmos_sdk_proto::cosmwasm::wasm::v1::ContractGrant {
contract: address,
limit: auth.limit.map(Into::into),
filter:auth.filter.map(Into::into),
}],
}
.to_bytes()?
.into(),
}
}
})
}
}

impl GrantConfigStorage {
pub fn try_into_grant_config(self, address: String) -> ContractResult<GrantConfig> {
Ok(GrantConfig {
description: self.description,
authorization: self.authorization.try_into_any(address)?,
optional: self.optional,
})
}
}

#[cw_serde]
pub struct FeeConfigStorage {
description: String,
pub allowance: Option<AllowanceData>,
pub expiration: Option<u32>,
}

#[cw_serde]
pub struct FeeConfig {
description: String,
pub allowance: Option<Any>,
pub expiration: Option<u32>,
}

#[cw_serde]
pub enum AllowanceData {
Any(Any),
AllowanceOnAccount(AllowanceOnAccount),
}
#[cw_serde]
pub struct AllowanceOnAccount {
pub allowance: Option<Any>,
}

impl FeeConfigStorage {
pub fn try_into_fee_config(self, address: String) -> ContractResult<FeeConfig> {
Ok(FeeConfig {
description: self.description,
allowance: match self.allowance {
None => None,
Some(allowance) => Some(allowance.try_into_any(address)?),
},
expiration: self.expiration,
})
}
}

impl AllowanceData {
pub fn try_into_any(self, address: String) -> ContractResult<Any> {
Ok(match self {
AllowanceData::Any(any) => any,
AllowanceData::AllowanceOnAccount(allowance) => {
// Handle the case where authorization is on the account itself
Any {
type_url: cosmos_sdk_proto::cosmwasm::wasm::v1::ContractExecutionAuthorization::full_name(),
value:
cosmos_sdk_proto::xion::v1::ContractsAllowance {
allowance: allowance.allowance.map(Into::into),
contract_addresses: vec![address]
}
.to_bytes()?
.into(),
}
}
})
}
}

#[cw_serde]
pub struct Any {
pub type_url: String,
Expand Down
37 changes: 23 additions & 14 deletions contracts/treasury/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::grant::{FeeConfig, GrantConfig};
use crate::grant::{FeeConfig, FeeConfigStorage, GrantConfig, GrantConfigStorage};
use crate::state::Params;
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Binary, Coin};
use cosmwasm_std::{Addr, Coin};

#[cw_serde]
pub struct InstantiateMsg {
pub admin: Option<Addr>,
pub type_urls: Vec<String>,
pub grant_configs: Vec<GrantConfig>,
pub fee_config: FeeConfig,
pub grant_configs: Vec<GrantConfigStorage>,
pub fee_config: FeeConfigStorage,
}

#[cw_serde]
Expand All @@ -20,13 +20,13 @@ pub enum ExecuteMsg {
CancelProposedAdmin {},
UpdateGrantConfig {
msg_type_url: String,
grant_config: GrantConfig,
grant_config: GrantConfigStorage,
},
RemoveGrantConfig {
msg_type_url: String,
},
UpdateFeeConfig {
fee_config: FeeConfig,
fee_config: FeeConfigStorage,
},
DeployFeeGrant {
authz_granter: Addr,
Expand All @@ -47,21 +47,30 @@ pub enum ExecuteMsg {
#[derive(QueryResponses)]
pub enum QueryMsg {
/// Query the grant config by type url
#[returns(Binary)]
GrantConfigByTypeUrl { msg_type_url: String },
#[returns(GrantConfig)]
GrantConfigByTypeUrl {
msg_type_url: String,
account_address: String,
},
/// Query the grant config by type url
#[returns(GrantConfigStorage)]
RawGrantConfigByTypeUrl { msg_type_url: String },

#[returns(Binary)]
#[returns(Vec<String>)]
GrantConfigTypeUrls {},

#[returns(Binary)]
FeeConfig {},
#[returns(FeeConfig)]
FeeConfig { address: String },

#[returns(FeeConfigStorage)]
RawFeeConfig {},

#[returns(Binary)]
#[returns(Addr)]
Admin {},

#[returns(Binary)]
#[returns(Addr)]
PendingAdmin {},

#[returns(Binary)]
#[returns(Params)]
Params {},
}
24 changes: 22 additions & 2 deletions contracts/treasury/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::grant::{FeeConfig, GrantConfig};
use crate::grant::{FeeConfig, FeeConfigStorage, GrantConfig, GrantConfigStorage};
use crate::state::{Params, ADMIN, FEE_CONFIG, GRANT_CONFIGS, PARAMS, PENDING_ADMIN};
use cosmwasm_std::{Addr, Order, StdResult, Storage};

Expand All @@ -12,14 +12,34 @@ pub fn grant_config_type_urls(store: &dyn Storage) -> StdResult<Vec<String>> {
pub fn grant_config_by_type_url(
store: &dyn Storage,
msg_type_url: String,
account_address: String,
) -> StdResult<GrantConfig> {
GRANT_CONFIGS
.load(store, msg_type_url)
.and_then(|grant_config| {
grant_config
.try_into_grant_config(account_address)
.map_err(Into::into)
})
}

pub fn raw_grant_config_by_type_url(
store: &dyn Storage,
msg_type_url: String,
) -> StdResult<GrantConfigStorage> {
GRANT_CONFIGS.load(store, msg_type_url)
}

pub fn fee_config(store: &dyn Storage) -> StdResult<FeeConfig> {
pub fn raw_fee_config(store: &dyn Storage) -> StdResult<FeeConfigStorage> {
FEE_CONFIG.load(store)
}

pub fn fee_config(store: &dyn Storage, address: String) -> StdResult<FeeConfig> {
FEE_CONFIG
.load(store)
.and_then(|fee_config| fee_config.try_into_fee_config(address).map_err(Into::into))
}

pub fn admin(store: &dyn Storage) -> StdResult<Addr> {
ADMIN.load(store)
}
Expand Down
6 changes: 3 additions & 3 deletions contracts/treasury/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::grant::{FeeConfig, GrantConfig};
use crate::grant::{FeeConfigStorage, GrantConfigStorage};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cw_storage_plus::{Item, Map};

// msg_type_url to grant config
pub const GRANT_CONFIGS: Map<String, GrantConfig> = Map::new("grant_configs");
pub const GRANT_CONFIGS: Map<String, GrantConfigStorage> = Map::new("grant_configs");

pub const FEE_CONFIG: Item<FeeConfig> = Item::new("fee_config");
pub const FEE_CONFIG: Item<FeeConfigStorage> = Item::new("fee_config");

pub const ADMIN: Item<Addr> = Item::new("admin");

Expand Down