Skip to content

Commit

Permalink
Merge pull request #371 from astroport-fi/merge/features_040823
Browse files Browse the repository at this point in the history
Release 3.3.0
  • Loading branch information
epanchee authored Aug 4, 2023
2 parents 8c69810 + c68bacf commit e53c4d1
Show file tree
Hide file tree
Showing 49 changed files with 7,644 additions and 507 deletions.
665 changes: 369 additions & 296 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ members = [
"contracts/router",
"contracts/token",
"contracts/whitelist",
"contracts/cw20_ics20",
"templates/*",
"contracts/tokenomics/generator",
"contracts/tokenomics/maker",
"contracts/tokenomics/staking",
"contracts/tokenomics/vesting",
"contracts/tokenomics/xastro_token",
"contracts/tokenomics/xastro_outpost_token",
"contracts/periphery/*",
]

Expand Down
6 changes: 6 additions & 0 deletions contracts/cw20_ics20/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[alias]
wasm = "build --release --lib --target wasm32-unknown-unknown"
wasm-debug = "build --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
integration-test = "test --test integration"
schema = "run --bin schema"
36 changes: 36 additions & 0 deletions contracts/cw20_ics20/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "astroport-cw20-ics20"
version = "1.1.1"
authors = ["Astroport", "Ethan Frey <[email protected]>"]
edition = "2021"
description = "IBC Enabled contracts that receives CW20 tokens and sends them over ICS20 to a remote chain with additional memo handling"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cw-plus"
homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"

[lib]
crate-type = ["cdylib", "rlib"]

[features]
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all init/handle/query exports
library = []

[dependencies]
cosmwasm-schema = { version = "1.1.0" }
cw-utils = "1.0.1"
cw2 = "1.1.0"
cw20 = "1.1.0"
cosmwasm-std = { version = "1.1.0", features = ["stargate"] }
cw-storage-plus = "1.0.1"
cw-controllers = "1.1.0"
schemars = "0.8.1"
semver = "1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.23" }

astroport = { path = "../../packages/astroport" }

[dev-dependencies]
cw20-ics20-original = { version = "0.13.4", package = "cw20-ics20" }
72 changes: 72 additions & 0 deletions contracts/cw20_ics20/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# CW20 ICS20

This is an *IBC Enabled* contract that allows us to send CW20 tokens from one chain over the standard ICS20
protocol to the bank module of another chain. In short, it lets us send our custom CW20 tokens with IBC and use
them just like native tokens on other chains.

It is only designed to send tokens and redeem previously sent tokens. It will not mint tokens belonging
to assets originating on the foreign chain. This is different than the Golang `ibctransfer` module, but
we properly implement ICS20 and respond with an error message... let's hope the Go side handles this correctly.

## IBC memo handling via a hook contract

If a memo is included in the message, we check for the existence of a hook contract handler. If an address is not set, it fails the transaction and refunds the user. If an address is set, the funds as well as the memo is forwarded for handling. Should the memo result in a failed transaction, everything is reverted and the user is refunded.

In the absence of a memo, funds are sent as usual.

## Workflow

The contract starts with minimal state. It just stores a default timeout in seconds for all packets it sends.
Most importantly it binds a local IBC port to enable channel connections.

An external party first needs to make one or more channels using this contract as one endpoint. It will use standard ics20
unordered channels for the version negotiation. Once established, it manages a list of known channels. You can use
[ts-relayer](https://github.com/confio/ts-relayer) `ibc-setup ics20` command to create these.

After there is at least one channel, you can send any CW20 token to this contract via the
[receiver pattern](https://github.com/CosmWasm/cw-plus/blob/master/packages/cw20/README.md#receiver).
The receive message must contain the channel to send over and the remote address to send to. It may optionally
include a custom timeout.

## Messages

It only accepts CW20ReceiveMsg from a cw20 contract. The data sent along with that message must be a JSON-serialized
TransferMsg:

```rust
pub struct TransferMsg {
/// The local channel to send the packets on
pub channel: String,
/// The remote address to send to
/// Don't use HumanAddress as this will likely have a different Bech32 prefix than we use
/// and cannot be validated locally
pub remote_address: String,
/// How long the packet lives in seconds. If not specified, use default_timeout
pub timeout: Option<u64>,
}
```

In addition, it supports directly sending native tokens via `ExecuteMsg::Transfer(TransferMsg)`.
You must send *exactly one* coin denom along with the transfer message, and that amount will be transfered
to the remote host.

## Queries

Queries only make sense relative to the established channels of this contract.

* `Port{}` - returns the port ID this contract has bound, so you can create channels. This info can be queried
via wasmd contract info query, but we expose another query here for convenience.
* `ListChannels{}` - returns a (currently unpaginated) list of all channels that have been created on this contract.
Returns their local channelId along with some basic metadata, like the remote port/channel and the connection they
run on top of.
* `Channel{id}` - returns more detailed information on one specific channel. In addition to the information available
in the list view, it returns the current outstanding balance on that channel, as well as the total amount that
has ever been sent on the channel.

## IBC Responses

These are defined by the ICS20 spec.

Notably, each Channel has a balance of tokens sent over that channel. If an incoming transfer request comes in for
a denom it does not know, or for a balance larger than we have sent, we will return an error in the acknowledgement
packet.
66 changes: 66 additions & 0 deletions contracts/cw20_ics20/src/amount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::error::ContractError;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Uint128};
use cw20::Cw20Coin;
use std::convert::TryInto;

#[cw_serde]
pub enum Amount {
Native(Coin),
// FIXME? USe Cw20CoinVerified, and validate cw20 addresses
Cw20(Cw20Coin),
}

impl Amount {
// TODO: write test for this
pub fn from_parts(denom: String, amount: Uint128) -> Self {
if denom.starts_with("cw20:") {
let address = denom.get(5..).unwrap().into();
Amount::Cw20(Cw20Coin { address, amount })
} else {
Amount::Native(Coin { denom, amount })
}
}

pub fn cw20(amount: u128, addr: &str) -> Self {
Amount::Cw20(Cw20Coin {
address: addr.into(),
amount: Uint128::new(amount),
})
}

pub fn native(amount: u128, denom: &str) -> Self {
Amount::Native(Coin {
denom: denom.to_string(),
amount: Uint128::new(amount),
})
}
}

impl Amount {
pub fn denom(&self) -> String {
match self {
Amount::Native(c) => c.denom.clone(),
Amount::Cw20(c) => format!("cw20:{}", c.address.as_str()),
}
}

pub fn amount(&self) -> Uint128 {
match self {
Amount::Native(c) => c.amount,
Amount::Cw20(c) => c.amount,
}
}

/// convert the amount into u64
pub fn u64_amount(&self) -> Result<u64, ContractError> {
Ok(self.amount().u128().try_into()?)
}

pub fn is_empty(&self) -> bool {
match self {
Amount::Native(c) => c.amount.is_zero(),
Amount::Cw20(c) => c.amount.is_zero(),
}
}
}
11 changes: 11 additions & 0 deletions contracts/cw20_ics20/src/bin/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_schema::write_api;

use astroport_cw20_ics20::msg::{ExecuteMsg, InitMsg, QueryMsg};

fn main() {
write_api! {
instantiate: InitMsg,
execute: ExecuteMsg,
query: QueryMsg,
}
}
Loading

0 comments on commit e53c4d1

Please sign in to comment.