Skip to content

Commit

Permalink
feat(xcvm): gateway: introduce GetLocalAssetByReference query (#4044)
Browse files Browse the repository at this point in the history
Required for merge:
- [x] `pr-workflow-check / draft-release-check` is ✅ success
- Other rules GitHub shows you, or can be read in
[configuration](../terraform/github.com/branches.tf)

Makes review faster:
- [x] PR title is my best effort to provide summary of changes and has
clear text to be part of release notes
- [x] I marked PR by `misc` label if it should not be in release notes
- [x] Linked Zenhub/Github/Slack/etc reference if one exists
- [x] I was clear on what type of deployment required to release my
changes (node, runtime, contract, indexer, on chain operation, frontend,
infrastructure) if any in PR title or description
- [x] Added reviewer into `Reviewers`
- [x] I tagged(`@`) or used other form of notification of one person who
I think can handle best review of this PR
- [x] I have proved that PR has no general regressions of relevant
features and processes required to release into production
- [x] Any dependency updates made, was done according guides from
relevant dependency
- Clicking all checkboxes
- Adding detailed description of changes when it feels appropriate (for
example when PR is big)
  • Loading branch information
mina86 authored Aug 10, 2023
1 parent 4f5277f commit 4ce68f0
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 26 deletions.
33 changes: 23 additions & 10 deletions code/xcvm/cosmwasm/contracts/gateway/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ use crate::{
auth,
error::{ContractError, Result},
events::make_event,
msg,
prelude::*,
state,
state::assets::{ASSETS, LOCAL_ASSETS},
};
use cosmwasm_std::{Deps, DepsMut, Response};
use xc_core::AssetId;

use crate::state::assets::*;

/// Adds a new asset to the registry; errors out if asset already exists.
pub(crate) fn force_asset(_: auth::Admin, deps: DepsMut, msg: AssetItem) -> Result {
state::assets::ASSETS.save(deps.storage, msg.asset_id, &msg)?;
let config = crate::state::load(deps.storage)?;
ASSETS.save(deps.storage, msg.asset_id, &msg)?;
if msg.from_network_id == config.here_id {
LOCAL_ASSETS.save(deps.storage, msg.local.clone(), &msg)?;
}
Ok(Response::new().add_event(
make_event("assets.forced")
.add_attribute("asset_id", msg.asset_id.to_string())
Expand All @@ -22,11 +23,18 @@ pub(crate) fn force_asset(_: auth::Admin, deps: DepsMut, msg: AssetItem) -> Resu
}

/// Fetches information about given asset.
pub(crate) fn get_asset_by_id(deps: Deps, asset_id: AssetId) -> Result<msg::GetAssetByIdResponse> {
ASSETS
.may_load(deps.storage, asset_id)?
.map(|reference| msg::GetAssetByIdResponse { asset: reference })
.ok_or(ContractError::UnsupportedAsset)
pub(crate) fn get_asset_by_id(deps: Deps, asset_id: AssetId) -> Result<AssetItem> {
ASSETS.may_load(deps.storage, asset_id)?.ok_or(ContractError::AssetNotFound)
}

/// Fetches information about given asset by its local reference.
pub(crate) fn get_local_asset_by_reference(
deps: Deps,
reference: AssetReference,
) -> Result<AssetItem> {
LOCAL_ASSETS
.may_load(deps.storage, reference)?
.ok_or(ContractError::AssetNotFound)
}

/// Removes an existing asset from the registry; errors out if asset doesn’t
Expand All @@ -36,7 +44,12 @@ pub(crate) fn force_remove_asset(
deps: DepsMut<'_>,
asset_id: AssetId,
) -> std::result::Result<Response, ContractError> {
let config = crate::state::load(deps.storage)?;
let asset = ASSETS.load(deps.storage, asset_id)?;
ASSETS.remove(deps.storage, asset_id);
if asset.from_network_id == config.here_id {
LOCAL_ASSETS.remove(deps.storage, asset.local);
}
Ok(Response::new()
.add_event(make_event("assets.removed").add_attribute("asset_id", asset_id.to_string())))
}
6 changes: 2 additions & 4 deletions code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ fn transfer_from_user(
.debug(serde_json_wasm::to_string(&(&program_funds, &host_funds))?.as_str());
let mut transfers = Vec::with_capacity(program_funds.0.len());
for (asset_id, Displayed(program_amount)) in program_funds.0.iter() {
let reference = assets::get_asset_by_id(deps.as_ref(), *asset_id)?.asset;
match reference.local {
match assets::get_asset_by_id(deps.as_ref(), *asset_id)?.local {
msg::AssetReference::Native { denom } => {
let Coin { amount: host_amount, .. } = host_funds
.iter()
Expand Down Expand Up @@ -223,8 +222,7 @@ fn send_funds_to_interpreter(
continue
}

let reference = assets::get_asset_by_id(deps, asset_id)?.asset;
let msg: CosmosMsg = match reference.local {
let msg = match assets::get_asset_by_id(deps, asset_id)?.local {
msg::AssetReference::Native { denom } => BankMsg::Send {
to_address: interpreter_address.clone(),
amount: vec![Coin::new(amount, denom)],
Expand Down
6 changes: 4 additions & 2 deletions code/xcvm/cosmwasm/contracts/gateway/src/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: msg::MigrateMsg) -> Result {
#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
pub fn query(deps: Deps, _env: Env, msg: msg::QueryMsg) -> Result<Binary> {
match msg {
msg::QueryMsg::GetAssetById { asset_id } => assets::get_asset_by_id(deps, asset_id)
.and_then(|resp| to_binary(&resp).map_err(ContractError::from)),
msg::QueryMsg::GetAssetById { asset_id } => assets::get_asset_by_id(deps, asset_id),
msg::QueryMsg::GetLocalAssetByReference { reference } =>
assets::get_local_asset_by_reference(deps, reference),
}
.and_then(|asset| Ok(to_binary(&msg::GetAssetResponse { asset })?))
}

#[cfg_attr(not(feature = "library"), cosmwasm_std::entry_point)]
Expand Down
4 changes: 2 additions & 2 deletions code/xcvm/cosmwasm/contracts/gateway/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ pub enum ContractError {
ICS20NotFound,
#[error("Could not serialize to JSON")]
FailedToSerialize,
#[error("The asset is not yet supported.")]
UnsupportedAsset,
#[error("Asset not been found in the registry.")]
AssetNotFound,
#[error("The contract must be initialized first.")]
NotInitialized,
#[error("An overflow occurred.")]
Expand Down
7 changes: 6 additions & 1 deletion code/xcvm/cosmwasm/contracts/gateway/src/state/assets.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use xc_core::{gateway::AssetItem, AssetId, NetworkId};
use xc_core::{
gateway::{config::AssetReference, AssetItem},
AssetId, NetworkId,
};

use crate::prelude::*;

/// when assets to be sent to other network it should be mapped before sent
pub(crate) const NETWORK_ASSET: Map<(AssetId, NetworkId), AssetId> = Map::new("network_asset");

pub(crate) const ASSETS: Map<AssetId, AssetItem> = Map::new("assets");

pub(crate) const LOCAL_ASSETS: Map<AssetReference, AssetItem> = Map::new("local_assets");
2 changes: 1 addition & 1 deletion code/xcvm/cosmwasm/contracts/interpreter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn external_query_lookup_asset(
let query = xc_core::gateway::QueryMsg::GetAssetById { asset_id };
let msg = WasmQuery::Smart { contract_addr: gateway_addr.into(), msg: to_binary(&query)? };
querier
.query::<xc_core::gateway::GetAssetByIdResponse>(&msg.into())
.query::<xc_core::gateway::GetAssetResponse>(&msg.into())
.map(|response| response.asset)
}

Expand Down
3 changes: 3 additions & 0 deletions code/xcvm/cosmwasm/contracts/interpreter/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ pub enum ContractError {

#[error("Not implemented")]
NotImplemented,

#[error("The asset is not yet supported.")]
UnsupportedAsset,
}
20 changes: 19 additions & 1 deletion code/xcvm/lib/core/src/gateway/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub struct OtherNetworkItem {
/// and about assets and services on these chains
/// (in future block hooks and some set of host extensions/precompiles would help to get some info
/// automatically)
/// `Force` message sets the data unconditionally.
/// `Force` message sets the data unconditionally.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "std", derive(schemars::JsonSchema))]
Expand Down Expand Up @@ -240,3 +240,21 @@ impl AssetReference {
}
}
}

#[cfg(feature = "cosmwasm")]
impl cw_storage_plus::PrimaryKey<'_> for AssetReference {
type Prefix = ();
type SubPrefix = ();
type Suffix = ();
type SuperSuffix = ();

#[inline]
fn key(&self) -> Vec<cw_storage_plus::Key<'_>> {
use cw_storage_plus::Key;
let (tag, value) = match self {
AssetReference::Native { denom } => (0, denom.as_bytes()),
AssetReference::Cw20 { contract } => (1, contract.as_bytes()),
};
vec![Key::Val8([tag]), Key::Ref(value)]
}
}
14 changes: 9 additions & 5 deletions code/xcvm/lib/core/src/gateway/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,18 @@ pub struct BridgeForwardMsg {
#[cfg_attr(feature = "std", derive(schemars::JsonSchema, QueryResponses))]
pub enum QueryMsg {
/// Returns [`AssetReference`] for an asset with given id.
#[cfg_attr(feature = "std", returns(GetAssetByIdResponse))]
#[cfg_attr(feature = "std", returns(GetAssetResponse))]
GetAssetById { asset_id: AssetId },

/// Returns [`AssetItem`] for an asset with given local reference.
#[cfg_attr(feature = "std", returns(GetAssetResponse))]
GetLocalAssetByReference { reference: AssetReference },
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "std", derive(schemars::JsonSchema))]
pub struct GetAssetByIdResponse {
pub struct GetAssetResponse {
pub asset: AssetItem,
}

Expand Down Expand Up @@ -148,7 +152,7 @@ mod tests {
},
"tip": "centauri12smx2wdlyttvyzvzg54y2vnqwq2qjatescq89n"
}
}
}
"#,
)
.unwrap(),
Expand Down Expand Up @@ -179,7 +183,7 @@ mod tests {
"salt": "6e6f6f705f776974685f6173736574",
"program": {
"tag": "6e6f6f705f776974685f6173736574",
"instructions": [
"instructions": [
]
},
"assets": [
Expand All @@ -188,7 +192,7 @@ mod tests {
},
"tip": "centauri12smx2wdlyttvyzvzg54y2vnqwq2qjatescq89n"
}
}
}
"#,
)
.unwrap(),
Expand Down

0 comments on commit 4ce68f0

Please sign in to comment.