-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #371 from astroport-fi/merge/features_040823
Release 3.3.0
- Loading branch information
Showing
49 changed files
with
7,644 additions
and
507 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} |
Oops, something went wrong.