diff --git a/.github/workflows/Basic.yml b/.github/workflows/Basic.yml index 095b757..243d933 100644 --- a/.github/workflows/Basic.yml +++ b/.github/workflows/Basic.yml @@ -71,7 +71,7 @@ jobs: - name: Run cargo clippy run: | - cargo clippy -- -D warnings + cargo clippy -- -W warnings - name: Generate schema run: | diff --git a/Cargo.lock b/Cargo.lock index a3ea73a..c61908c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,16 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bigint" +version = "4.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def" +dependencies = [ + "byteorder", + "crunchy 0.1.6", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -145,6 +155,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "common" version = "0.1.0" @@ -304,6 +323,18 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -366,12 +397,12 @@ dependencies = [ "cw-mock-ibc-core", "cw-multi-test", "cw-storage-plus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw-utils", + "cw-utils 1.0.1", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-manager", - "cw2", - "cw20", + "cw2 1.1.0", + "cw20 1.1.0", "cw20-base", "debug_print", "schemars", @@ -391,7 +422,7 @@ dependencies = [ "cw-storage-plus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", - "cw20", + "cw20 1.1.0", "cw20-base", "hex", "regex", @@ -454,7 +485,7 @@ checksum = "f219a9606c7f447535bc0283d8d4077e1f71c28d3387e92c4f06c155c65e438c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw20", + "cw20 1.1.0", "thiserror", ] @@ -477,8 +508,9 @@ dependencies = [ "cw-xcall 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-manager", - "cw2", - "cw20", + "cw2 1.1.0", + "cw20 1.1.0", + "cw20-adapter", "cw20-base", "debug_print", "getrandom", @@ -488,6 +520,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw-item-set" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05dad9dc2e6e9ab784bb5598d8528f4afe014b7b0ec05e1f466fe2e11aca368c" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus 0.16.0", +] + [[package]] name = "cw-mock-ibc-connection" version = "0.1.0" @@ -501,7 +543,7 @@ dependencies = [ "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", - "cw2", + "cw2 1.1.0", "debug_print", "hex", "schemars", @@ -522,7 +564,7 @@ dependencies = [ "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", - "cw2", + "cw2 1.1.0", "debug_print", "hex", "schemars", @@ -542,7 +584,7 @@ dependencies = [ "cw-common 0.1.0 (git+https://github.com/icon-project/IBC-Integration.git?branch=main)", "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", - "cw2", + "cw2 1.1.0", "hex", "schemars", "serde", @@ -558,7 +600,7 @@ dependencies = [ "anyhow", "cosmwasm-std", "cw-storage-plus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw-utils", + "cw-utils 1.0.1", "derivative", "itertools", "k256 0.11.6", @@ -568,6 +610,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw-storage-plus" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "cw-storage-plus" version = "1.1.0" @@ -589,6 +653,21 @@ dependencies = [ "serde", ] +[[package]] +name = "cw-utils" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.16.0", + "schemars", + "semver", + "serde", + "thiserror", +] + [[package]] name = "cw-utils" version = "1.0.1" @@ -597,7 +676,7 @@ checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2", + "cw2 1.1.0", "schemars", "semver", "serde", @@ -615,7 +694,7 @@ dependencies = [ "cosmwasm-storage", "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xCall.git?branch=main)", - "cw2", + "cw2 1.1.0", "debug_print", "schemars", "serde", @@ -633,7 +712,7 @@ dependencies = [ "cosmwasm-storage", "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", - "cw2", + "cw2 1.1.0", "debug_print", "schemars", "serde", @@ -649,7 +728,7 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", - "cw2", + "cw2 1.1.0", "debug_print", "schemars", "serde", @@ -665,7 +744,7 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cw-storage-plus 1.1.0 (git+https://github.com/icon-project/cw-storage-plus.git?branch=fix-raw)", - "cw2", + "cw2 1.1.0", "debug_print", "schemars", "serde", @@ -687,10 +766,10 @@ dependencies = [ "cw-mock-ibc-core", "cw-multi-test", "cw-storage-plus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw-utils", + "cw-utils 1.0.1", "cw-xcall 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", "cw-xcall-lib 0.1.0 (git+https://github.com/icon-project/xcall-multi.git?branch=main)", - "cw2", + "cw2 1.1.0", "cw20-base", "debug_print", "schemars", @@ -698,6 +777,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw2" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "schemars", + "serde", +] + [[package]] name = "cw2" version = "1.1.0" @@ -712,6 +804,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw20" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45a8794a5dd33b66af34caee52a7beceb690856adcc1682b6e3db88b2cdee62" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "schemars", + "serde", +] + [[package]] name = "cw20" version = "1.1.0" @@ -720,11 +825,27 @@ checksum = "011c45920f8200bd5d32d4fe52502506f64f2f75651ab408054d4cfc75ca3a9b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils", + "cw-utils 1.0.1", "schemars", "serde", ] +[[package]] +name = "cw20-adapter" +version = "1.0.0" +source = "git+https://github.com/InjectiveLabs/cw20-adapter.git?branch=master#5bae23a4b2a3849d7bfa736c06f76cfaae04baa5" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-item-set", + "cw-storage-plus 0.16.0", + "cw2 0.16.0", + "cw20 0.16.0", + "injective-cosmwasm", + "serde", + "thiserror", +] + [[package]] name = "cw20-base" version = "1.1.0" @@ -734,9 +855,9 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw-utils", - "cw2", - "cw20", + "cw-utils 1.0.1", + "cw2 1.1.0", + "cw20 1.1.0", "schemars", "semver", "serde", @@ -951,6 +1072,42 @@ dependencies = [ "libc", ] +[[package]] +name = "ethbloom" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3932e82d64d347a045208924002930dc105a138995ccdc1479d0f05f0359f17c" +dependencies = [ + "crunchy 0.2.2", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b054df51e53f253837ea422681215b42823c02824bde982699d0dceecf6165a1" +dependencies = [ + "crunchy 0.2.2", + "ethbloom", + "ethereum-types-serialize", + "fixed-hash", + "serde", + "uint", +] + +[[package]] +name = "ethereum-types-serialize" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" +dependencies = [ + "serde", +] + [[package]] name = "fastrand" version = "2.0.0" @@ -977,6 +1134,19 @@ dependencies = [ "subtle", ] +[[package]] +name = "fixed-hash" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1a683d1234507e4f3bf2736eeddf0de1dc65996dc0164d57eba0a74bcf29489" +dependencies = [ + "byteorder", + "heapsize", + "rand", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -998,6 +1168,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures" version = "0.3.28" @@ -1118,6 +1294,15 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +dependencies = [ + "winapi", +] + [[package]] name = "heck" version = "0.4.1" @@ -1129,6 +1314,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-buffer-serde" @@ -1194,6 +1382,24 @@ dependencies = [ "sha3", ] +[[package]] +name = "impl-rlp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +dependencies = [ + "serde", +] + [[package]] name = "indexmap" version = "2.0.0" @@ -1204,6 +1410,37 @@ dependencies = [ "hashbrown 0.14.0", ] +[[package]] +name = "injective-cosmwasm" +version = "0.1.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74b2d3b5cfe251bfe4d7f1aea33ad98886f2a01cefafaac4e14e86ad23822729" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "ethereum-types", + "hex", + "injective-math", + "schemars", + "serde", + "serde_repr", + "subtle-encoding", +] + +[[package]] +name = "injective-math" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b28dc06633a0fc1ac0345d350ff6ecead60989119a985c94053ce9448c1aa9" +dependencies = [ + "bigint", + "cosmwasm-std", + "ethereum-types", + "schemars", + "serde", + "subtle-encoding", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1512,6 +1749,34 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -1595,6 +1860,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rlp" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73" +dependencies = [ + "rustc-hex", +] + [[package]] name = "rlp-derive" version = "0.1.0" @@ -1881,6 +2155,12 @@ dependencies = [ "der 0.7.8", ] +[[package]] +name = "static_assertions" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" + [[package]] name = "subtle" version = "2.5.0" @@ -2021,12 +2301,33 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +dependencies = [ + "crunchy 0.2.2", +] + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uint" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +dependencies = [ + "byteorder", + "crunchy 0.2.2", + "heapsize", + "rustc-hex", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -2063,6 +2364,28 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/README.md b/README.md index b64c354..94fd6c0 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,40 @@ [rust-cov-badge]: https://codecov.io/gh/balancednetwork/balanced-rust-contracts/branch/main/graph/badge.svg?flag=rust Rust contracts for Balanced xCall integrations +## General Build +To build the contract and verify built wasm file run following script: + +`./scripts/generate_wasm.sh` + + +## Chain Specific Build +To build the contract for specific chain with its own features, enable the feature as default by modifying `Cargo.toml`. + +### Chain Injective +For injective chain we enable feature `injective` in all projects and subprojects by modifying feature section as follows: +``` +[features] +default=["injective"] +``` +#### Additional Steps Injective +- Call method `SetAdapter` on this contract to set adapter contract. +``` +injectived tx wasm execute ${TOKEN_CONTRACT} '{"set_adapter":{"registry_contract":"${REGISTRY_CONTRACT}"}}' --from ${WALLET} --keyring-backend test --node https://injective-testnet-rpc.publicnode.com:443 --chain-id injective-888 --gas-prices 500000000inj --gas auto --gas-adjustment 1.5 -y --output json +``` +- Register this contract to CW20Adapter contract by calling `RegisterCW20` on adapter contract. +``` +injectived tx wasm execute ${REGISTRY_CONTRACT} '{"register_cw20_contract":{"addr":"${TOKEN_CONTRACT}"}}' --from ${WALLET} --keyring-backend test --amount 1000000000000000000inj --node https://injective-testnet-rpc.publicnode.com:443 --chain-id injective-888 --gas-prices 500000000inj --gas auto --gas-adjustment 1.5 -y --output json +``` +- Update metadata on CW20Adapter by calling `UpdateMetadata`. +``` +injectived tx wasm execute ${REGISTRY_CONTRACT} '{"update_metadata":{"addr":"${TOKEN_CONTRACT}"}}' --from ${WALLET} --keyring-backend test --amount 1000000000000000000inj --node https://injective-testnet-rpc.publicnode.com:443 --chain-id injective-888 --gas-prices 500000000inj --gas auto --gas-adjustment 1.5 -y --output json + +``` +After properly setup we should be able to query balance transferred to user as denom token balance as follows: +``` +injectived query bank spendable-balance ${USER_ACCOUNT} factory/${REGISTRY_CONTRACT}/${TOKEN_CONTRACT} --node https://injective-testnet-rpc.publicnode.com:443 --chain-id injective-888 +``` + + diff --git a/contracts/cw-common/Cargo.toml b/contracts/cw-common/Cargo.toml index f800a64..d4807af 100644 --- a/contracts/cw-common/Cargo.toml +++ b/contracts/cw-common/Cargo.toml @@ -8,6 +8,11 @@ edition = "2021" [lib] crate-type = ["cdylib", "rlib"] +[features] +default=[] +# use injective to enable injective specific code +injective=[] + [dependencies] bytes = { version = "1.4.0", default-features = false } rlp-derive = { version = "0.1.0", default-features = false } diff --git a/contracts/cw-common/src/hub_token_msg.rs b/contracts/cw-common/src/hub_token_msg.rs index 29e4b16..6564ec4 100644 --- a/contracts/cw-common/src/hub_token_msg.rs +++ b/contracts/cw-common/src/hub_token_msg.rs @@ -80,6 +80,8 @@ pub enum ExecuteMsg { /// a new minter. Setting the minter to None will remove the /// token's minter forever. UpdateMinter { new_minter: Option }, + #[cfg(feature = "injective")] + SetAdapter { registry_contract: String }, } #[cw_serde] diff --git a/contracts/token-contracts/cw-hub-bnusd/Cargo.toml b/contracts/token-contracts/cw-hub-bnusd/Cargo.toml index 4c15f4b..b4a8391 100644 --- a/contracts/token-contracts/cw-hub-bnusd/Cargo.toml +++ b/contracts/token-contracts/cw-hub-bnusd/Cargo.toml @@ -16,10 +16,13 @@ exclude = [ crate-type = ["cdylib", "rlib"] [features] +default=[] # for more explicit tests, cargo test --features=backtraces backtraces = ["cosmwasm-std/backtraces"] # use library feature to disable all instantiate/execute/query exports library = [] +# use injective to enable injective specific code +injective=[] [package.metadata.scripts] optimize = """docker run --rm -v "$(pwd)":/code \ @@ -44,6 +47,7 @@ cw-common = { path = "../../cw-common" } hex = "0.4.3" debug_print = {workspace=true} cw_ibc_rlp_lib = {git = "https://github.com/icon-project/IBC-Integration.git", branch="main", package = "common"} +cw20-adapter = { git= "https://github.com/InjectiveLabs/cw20-adapter.git",branch="master", features=["library"]} # cw20-base = { path = "../../cw20-base" } diff --git a/contracts/token-contracts/cw-hub-bnusd/src/contract.rs b/contracts/token-contracts/cw-hub-bnusd/src/contract.rs index 578f99f..54ebba7 100644 --- a/contracts/token-contracts/cw-hub-bnusd/src/contract.rs +++ b/contracts/token-contracts/cw-hub-bnusd/src/contract.rs @@ -39,7 +39,13 @@ use cw_common::network_address::NetworkAddress; use cw_ibc_rlp_lib::rlp::Rlp; use debug_print::debug_println; +#[cfg(feature = "injective")] +use crate::cw20_adapter::CW20Adapter; +#[cfg(feature = "injective")] +use crate::state::CW20_ADAPTER; + use cw_common::data_types::{CrossTransfer, CrossTransferRevert}; + const CONTRACT_NAME: &str = "crates.io:cw-hub-bnusd"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -161,6 +167,15 @@ pub fn execute( ExecuteMsg::UpdateMinter { new_minter } => { execute_update_minter(deps, env, info, new_minter).map_err(ContractError::Cw20BaseError) } + #[cfg(feature = "injective")] + ExecuteMsg::SetAdapter { registry_contract } => { + let owner = OWNER.load(deps.storage)?; + assert!(owner == info.sender); + let registry = deps.api.addr_validate(®istry_contract)?; + let adapter = CW20Adapter::new(env.contract.address, registry); + CW20_ADAPTER.save(deps.storage, &adapter)?; + Ok(Response::new()) + } } } @@ -207,14 +222,15 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { let cross_transfer_data: CrossTransfer = decode(&data).unwrap(); - x_cross_transfer(deps, env, info, from, cross_transfer_data)?; + x_cross_transfer(deps, env, info, from, cross_transfer_data) } X_CROSS_TRANSFER_REVERT => { let cross_transfer_revert_data: CrossTransferRevert = decode(&data).unwrap(); - x_cross_transfer_revert(deps, env, info, from, cross_transfer_revert_data)?; + x_cross_transfer_revert(deps, env, info, from, cross_transfer_revert_data) } _ => { return Err(ContractError::InvalidMethod); } - } + }; + res = res.map(|res| res.add_attribute("action", "handle_call_message")); - Ok(Response::new().add_attribute("action", "handle_call_message")) + res } pub fn cross_transfer( deps: DepsMut, env: Env, - info: MessageInfo, + mut info: MessageInfo, to: NetworkAddress, amount: u128, data: Vec, ) -> Result { ensure!(amount > 0, ContractError::InvalidAmount); - let funds = info.funds.clone(); + let info_copy = info.clone(); let nid = NID.load(deps.storage)?; let hub_net: NetId = DESTINATION_TOKEN_NET.load(deps.storage)?; let hub_address: Addr = DESTINATION_TOKEN_ADDRESS.load(deps.storage)?; let sender = &info.sender; + #[cfg(feature = "injective")] + { + let adapter: CW20Adapter = CW20_ADAPTER.load(deps.storage)?; + let (_adpater_funds, other) = adapter.split_adapter_funds(&info); + info.funds = other; + } + let from = NetworkAddress::new(&nid.to_string(), info.sender.as_ref()); let call_data = CrossTransfer { @@ -331,22 +355,48 @@ mod execute { let wasm_execute_message: CosmosMsg = CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute { contract_addr: X_CALL.load(deps.storage).unwrap().to_string(), msg: to_binary(&call_message)?, - funds, + funds: info.funds.clone(), }); let sub_message = SubMsg::new(wasm_execute_message); debug_println!("this is {:?}", info.sender); debug_println!("burn from {:?}", sub_message); - - let result = - execute_burn(deps, env, info, amount.into()).map_err(ContractError::Cw20BaseError)?; let event = emit_cross_transfer_event("CrossTransfer".to_string(), from, to, amount, data); - - Ok(result - .add_submessage(sub_message) + #[cfg(feature = "injective")] + { + let adapter = CW20_ADAPTER.load(deps.storage)?; + let tf_tokens = adapter.get_adapter_fund(&info_copy); + let mut response = cw20_base::allowances::execute_increase_allowance( + deps, + env, + info.clone(), + env.contract.address.to_string(), + amount.into(), + None, + ) + .expect("Failed To Increase Allowance") .add_attribute("method", "cross_transfer") - .add_event(event)) + .add_event(event); + if tf_tokens > 0 { + response = response.add_submessage(adapter.redeem(tf_tokens, &info.sender)); + } + response = response.add_submessage(sub_message); + response = response.add_message(adapter.burn_user_cw20_token(amount, &info.sender)); + Ok(response) + } + + #[cfg(not(feature = "injective"))] + { + let mut result = execute_burn(deps, env, info, amount.into()) + .map_err(ContractError::Cw20BaseError)?; + + result = result + .add_submessage(sub_message) + .add_attribute("method", "cross_transfer") + .add_event(event); + Ok(result) + } } pub fn x_cross_transfer( @@ -381,26 +431,54 @@ mod execute { .addr_validate(account.as_ref()) .map_err(ContractError::Std)?; debug_println!("mint to {:?}", account); - let res = execute_mint( - deps, - env, - info, - account.to_string(), - cross_transfer_data.value.into(), - ) - .expect("Fail to mint"); let event = emit_cross_transfer_event( "CrossTransfer".to_string(), cross_transfer_data.from, - cross_transfer_data.to, + cross_transfer_data.to.clone(), cross_transfer_data.value, cross_transfer_data.data, ); - Ok(res - .add_attribute("method", "x_cross_transfer") - .add_event(event)) + #[cfg(feature = "injective")] + { + let adapter = CW20_ADAPTER.load(deps.storage)?; + let mut res = execute_mint( + deps, + env, + info.clone(), + adapter.adapter_contract().to_string(), + cross_transfer_data.value.into(), + ) + .expect("Fail to mint"); + let receive_msg = adapter.receive( + &cross_transfer_data.to.account(), + cross_transfer_data.value.into(), + ); + res = res + .add_submessage(receive_msg) + .add_attribute("method", "x_cross_transfer") + .add_event(event); + Ok(res) + } + + #[cfg(not(feature = "injective"))] + { + let mut res = execute_mint( + deps, + env, + info, + cross_transfer_data.to.account().to_string(), + cross_transfer_data.value.into(), + ) + .expect("Fail to mint"); + + res = res + .add_attribute("method", "x_cross_transfer") + .add_event(event); + + Ok(res) + } } pub fn x_cross_transfer_revert( @@ -419,23 +497,49 @@ mod execute { deps.api .addr_validate(cross_transfer_revert_data.from.as_ref()) .map_err(ContractError::Std)?; - - let res = execute_mint( - deps, - env, - info, - cross_transfer_revert_data.from.to_string(), - cross_transfer_revert_data.value.into(), - ) - .expect("Fail to mint"); let event = emit_cross_transfer_revert_event( "CrossTransferRevert".to_string(), - cross_transfer_revert_data.from, + cross_transfer_revert_data.from.clone(), cross_transfer_revert_data.value, ); - Ok(res - .add_attribute("method", "x_cross_transfer_revert") - .add_event(event)) + + #[cfg(feature = "injective")] + { + let adapter = CW20_ADAPTER.load(deps.storage)?; + let mut res = execute_mint( + deps, + env, + info.clone(), + adapter.adapter_contract().to_string(), + cross_transfer_revert_data.value.into(), + ) + .expect("Fail to mint"); + let receive_msg = adapter.receive( + &cross_transfer_revert_data.from, + cross_transfer_revert_data.value.clone(), + ); + res = res + .add_submessage(receive_msg) + .add_attribute("method", "x_cross_transfer_revert") + .add_event(event); + Ok(res) + } + + #[cfg(not(feature = "injective"))] + { + let mut res = execute_mint( + deps, + env, + info, + cross_transfer_revert_data.from.to_string(), + cross_transfer_revert_data.value.into(), + ) + .expect("Fail to mint"); + res = res + .add_attribute("method", "x_cross_transfer_revert") + .add_event(event); + Ok(res) + } } } diff --git a/contracts/token-contracts/cw-hub-bnusd/src/cw20_adapter.rs b/contracts/token-contracts/cw-hub-bnusd/src/cw20_adapter.rs new file mode 100644 index 0000000..c6d91d3 --- /dev/null +++ b/contracts/token-contracts/cw-hub-bnusd/src/cw20_adapter.rs @@ -0,0 +1,110 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::SubMsg; +use cosmwasm_std::{coin, to_binary, Addr, BankMsg, Binary, CosmosMsg, WasmMsg}; +use cosmwasm_std::{Coin, MessageInfo}; +use cw20_adapter::msg::ExecuteMsg as Cw20AdapterMsg; +use cw_common::hub_token_msg::ExecuteMsg as TokenExecuteMsg; + +#[cw_serde] +pub struct CW20Adapter { + token_contract: Addr, + adapter_contract: Addr, +} + +impl CW20Adapter { + pub fn new(token_contract: Addr, adapter_contract: Addr) -> Self { + return Self { + token_contract, + adapter_contract, + }; + } + // convert specified TF tokens to our token and transfer to receiver + pub fn redeem(&self, amount: u128, receiver: &Addr) -> SubMsg { + let fund = coin(amount, self.denom()); + let message = Cw20AdapterMsg::RedeemAndTransfer { + recipient: Some(receiver.to_string()), + }; + + let msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.adapter_contract.to_string(), + msg: to_binary(&message).unwrap(), + funds: vec![fund], + }); + let submessage = SubMsg { + id: 2, + msg, + gas_limit: None, + reply_on: cosmwasm_std::ReplyOn::Never, + }; + submessage + } + // mint equivalent TF tokens for the receiver + pub fn receive(&self, receiver: &Addr, amount: u128) -> SubMsg { + let msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.adapter_contract.to_string(), + msg: to_binary(&Cw20AdapterMsg::Receive { + sender: receiver.to_string(), + amount: amount.into(), + msg: Binary::default(), + }) + .unwrap(), + funds: vec![], + }); + let submessage = SubMsg { + id: 1, + msg, + gas_limit: None, + reply_on: cosmwasm_std::ReplyOn::Never, + }; + submessage + } + // transfer tf tokens from this contract to user. + pub fn transfer(&self, recepient: &Addr, amount: u128) -> CosmosMsg { + return CosmosMsg::Bank(BankMsg::Send { + to_address: recepient.to_string(), + amount: vec![coin(amount, self.denom())], + }); + } + // burn users cw20 tokens after redeem + pub fn burn_user_cw20_token(&self, amount: u128, owner: &Addr) -> CosmosMsg { + let msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.token_contract.to_string(), + msg: to_binary(&TokenExecuteMsg::BurnFrom { + owner: owner.to_string(), + amount: amount.into(), + }) + .unwrap(), + funds: vec![], + }); + msg + } + + pub fn denom(&self) -> String { + format!("factory/{}/{}", self.adapter_contract, self.token_contract) + } + + pub fn adapter_contract(&self) -> &Addr { + &self.adapter_contract + } + + pub fn get_adapter_fund(&self, info: &MessageInfo) -> u128 { + info.funds + .iter() + .filter_map(|f| { + if f.denom == self.denom() { + return Some(f.amount.u128()); + } + None + }) + .sum() + } + + pub fn split_adapter_funds(&self, info: &MessageInfo) -> (Vec, Vec) { + let (adapter, other) = info + .funds + .clone() + .into_iter() + .partition(|f| f.denom == self.denom()); + return (adapter, other); + } +} diff --git a/contracts/token-contracts/cw-hub-bnusd/src/lib.rs b/contracts/token-contracts/cw-hub-bnusd/src/lib.rs index 2243acd..bd8239f 100644 --- a/contracts/token-contracts/cw-hub-bnusd/src/lib.rs +++ b/contracts/token-contracts/cw-hub-bnusd/src/lib.rs @@ -1,5 +1,7 @@ pub mod constants; pub mod contract; +#[cfg(feature = "injective")] +pub mod cw20_adapter; mod error; pub mod events; pub mod helpers; diff --git a/contracts/token-contracts/cw-hub-bnusd/src/state.rs b/contracts/token-contracts/cw-hub-bnusd/src/state.rs index bbf08b5..9409158 100644 --- a/contracts/token-contracts/cw-hub-bnusd/src/state.rs +++ b/contracts/token-contracts/cw-hub-bnusd/src/state.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "injective")] +use super::cw20_adapter::CW20Adapter; use cosmwasm_std::Addr; use cw_common::network_address::{NetId, NetworkAddress}; use cw_storage_plus::Item; @@ -9,3 +11,6 @@ pub const X_CALL_NETWORK_ADDRESS: Item = Item::new("xCallBTPAddr pub const NID: Item = Item::new("nid"); pub const DESTINATION_TOKEN_ADDRESS: Item = Item::new("hubAddress"); pub const DESTINATION_TOKEN_NET: Item = Item::new("hubNet"); + +#[cfg(feature = "injective")] +pub const CW20_ADAPTER: Item = Item::new("cw20_adapter");