Skip to content
Merged
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
1 change: 1 addition & 0 deletions code/Cargo.lock

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

28 changes: 27 additions & 1 deletion code/xcvm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ Can be considered as 3 layers,

For each chain and protocol it makes pragmatics hacks to use existing liquidity and execution primitives.

### Examples

#### Stake on Strides

Program to `Stake` on Stride and transfer staked token to Osmosis
is detected as pattern expressed in XCVM.

That part of program is translated to IBC calls to Stride without contracts deployed.

So this program is possible
```
Osmosis ATOM ->
Spawn(Stride, ATOM) -> Stake(ATOM) + Spawn(Osmosis, stATOM)
-> Spawn(Centauri, stATOM)
```

### ICS-20 Memo as `Spawn` carrier

`Spawn` forms `ICS-20` packet with `memo`.
Expand All @@ -69,4 +85,14 @@ For each chain and protocol it makes pragmatics hacks to use existing liquidity

`xc-master` contract verifies amount sent and proceed with move of assets up to amount in message via delegation from `xc-account`.

Approach is needed because there is no `amount` information can be securely transferred in `memo`.
Approach is needed because there is no `amount` information can be securely transferred in `memo`.

### Asset id encoding

Each asset id is 128 bit number with 4 first bytes are network id, means that numbers never overlap.

So it will not be the case that on one chain 123213 means PEPA and on other chain 123213 means SHIB.

Prefix allows to find network to look at for asset info.

For security reasons when assets sent from chain to chain, asset id changes.
Comment thread
dzmitry-lahoda marked this conversation as resolved.
2 changes: 1 addition & 1 deletion code/xcvm/cosmwasm/contracts/gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Hides custom entry points and messaging under unified security, routing, assets


Is Entrypoint and exit for Programs. Also handles interactions with [OTP](otp.md).
Book keeps per-chain state. Holds the address mappings for cross-chain accounts and instantiates new interpreters.
Book keeps per-chain state. Holds the address mappings for cross-chain accounts and instantiates new interpreters.
2 changes: 1 addition & 1 deletion code/xcvm/cosmwasm/contracts/gateway/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ pub(crate) fn force_remove_asset(
) -> std::result::Result<Response, ContractError> {
ASSETS.remove(deps.storage, asset_id);
Ok(Response::new()
.add_event(make_event("unregister").add_attribute("asset_id", asset_id.to_string())))
.add_event(make_event("assets.removed").add_attribute("asset_id", asset_id.to_string())))
}
8 changes: 4 additions & 4 deletions code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ fn transfer_from_user(
return Err(ContractError::InsufficientFunds)?
}
},
msg::AssetReference::Virtual { cw20_address } =>
transfers.push(Cw20Contract(cw20_address).call(Cw20ExecuteMsg::TransferFrom {
msg::AssetReference::Cw20 { contract } =>
transfers.push(Cw20Contract(contract).call(Cw20ExecuteMsg::TransferFrom {
owner: user.to_string(),
recipient: self_address.to_string(),
amount: (*amount).into(),
Expand Down Expand Up @@ -232,8 +232,8 @@ fn send_funds_to_interpreter(
amount: vec![Coin::new(amount, denom)],
}
.into(),
msg::AssetReference::Virtual { cw20_address } => {
let contract = Cw20Contract(cw20_address);
msg::AssetReference::Cw20 { contract } => {
let contract = Cw20Contract(contract);
contract.call(Cw20ExecuteMsg::Transfer {
recipient: interpreter_address.clone(),
amount: amount.into(),
Expand Down
33 changes: 16 additions & 17 deletions code/xcvm/cosmwasm/contracts/interpreter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ pub fn interpret_call(
asset_id,
)?;
match reference.local {
AssetReference::Virtual { cw20_address } =>
Cow::Owned(cw20_address.into_string().into()),
AssetReference::Cw20 { contract } =>
Cow::Owned(contract.into_string().into()),
AssetReference::Native { denom } => Cow::Owned(denom.into()),
}
},
Expand All @@ -242,10 +242,10 @@ pub fn interpret_call(
asset_id,
)?;
let amount = match reference.local {
AssetReference::Virtual { cw20_address } => apply_amount_to_cw20_balance(
AssetReference::Cw20 { contract } => apply_amount_to_cw20_balance(
deps,
&balance,
&cw20_address,
&contract,
&env.contract.address,
),
AssetReference::Native { denom } =>
Expand Down Expand Up @@ -308,10 +308,10 @@ pub fn interpret_spawn(
.apply(coin.amount.into())
.map_err(|_| ContractError::ArithmeticError)
},
AssetReference::Virtual { cw20_address } => apply_amount_to_cw20_balance(
AssetReference::Cw20 { contract } => apply_amount_to_cw20_balance(
deps.as_ref(),
&balance,
cw20_address,
contract,
&env.contract.address,
),
}?;
Expand All @@ -324,12 +324,11 @@ pub fn interpret_spawn(
to_address: gateway_address.clone().into(),
amount: vec![Coin { denom, amount: transfer_amount.into() }],
}),
AssetReference::Virtual { cw20_address } => response.add_message(
Cw20Contract(cw20_address).call(Cw20ExecuteMsg::Transfer {
AssetReference::Cw20 { contract } =>
response.add_message(Cw20Contract(contract).call(Cw20ExecuteMsg::Transfer {
recipient: gateway_address.clone().into(),
amount: transfer_amount.into(),
})?,
),
})?),
};
}
}
Expand Down Expand Up @@ -396,12 +395,12 @@ pub fn interpret_transfer(
amount: vec![coin],
})
},
AssetReference::Virtual { cw20_address } => {
let contract = Cw20Contract(cw20_address.clone());
AssetReference::Cw20 { contract } => {
let contract = Cw20Contract(contract.clone());
let transfer_amount = apply_amount_to_cw20_balance(
deps.as_ref(),
&balance,
&cw20_address,
&contract.0,
&env.contract.address,
)?;
response.add_message(contract.call(Cw20ExecuteMsg::Transfer {
Expand Down Expand Up @@ -463,25 +462,25 @@ fn handle_call_result(deps: DepsMut, msg: Reply) -> StdResult<Response> {
/// Calculates and returns the actual balance to process
///
/// * `balance`: Balance to be transformed into the actual balance
/// * `cw20_address`: Address of the corresponding cw20 contract
/// * `contract`: Address of the corresponding cw20 contract
/// * `self_address`: This interpreter's address
fn apply_amount_to_cw20_balance<A: Into<String> + Clone>(
deps: Deps,
balance: &Balance,
cw20_address: A,
contract: A,
self_address: A,
) -> Result<u128> {
let balance_response =
deps.querier.query::<BalanceResponse>(&QueryRequest::Wasm(WasmQuery::Smart {
contract_addr: cw20_address.clone().into(),
contract_addr: contract.clone().into(),
msg: to_binary(&Cw20QueryMsg::Balance { address: self_address.into() })?,
}))?;

if balance.is_unit {
// If the balance is unit, we need to take `decimals` into account.
let token_info =
deps.querier.query::<TokenInfoResponse>(&QueryRequest::Wasm(WasmQuery::Smart {
contract_addr: cw20_address.into(),
contract_addr: contract.into(),
msg: to_binary(&Cw20QueryMsg::TokenInfo {})?,
}))?;
balance
Expand Down
4 changes: 2 additions & 2 deletions code/xcvm/cosmwasm/tests/src/tests/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ impl<T> TestVM<XCVMState<T>> {
(ConfigSubMsg::ForceAsset(AssetItem {
asset_id,
from_network_id: todo!("restore"),
local: xc_core::gateway::AssetReference::Virtual {
cw20_address: asset_address.clone().into(),
local: xc_core::gateway::AssetReference::Cw20 {
contract: asset_address.clone().into(),
},
bridged: None,
})),
Expand Down
3 changes: 3 additions & 0 deletions code/xcvm/lib/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ strum.workspace = true
thiserror = { workspace = true }
ibc-proto = { workspace = true, default-features = false, features = ["serde", "parity-scale-codec"]}
serde-cw-value = { workspace = true, default-features = false}
xcm = { workspace = true, default-features = false, optional = true}

[build-dependencies]
prost-build = { workspace = true }

[features]
default = ["std"]
cosmwasm = ["cw-storage-plus", "cw20"]
substrate = ["xcm"]
std = [
"cosmwasm-std/std",
"xcm/std",
"cw-storage-plus/std",
"dep:cosmwasm-schema",
"dep:schemars",
Expand Down
Loading