diff --git a/.gitmodules b/.gitmodules
index a0341be62..6a32e7a26 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "lib-openrml"]
path = lib-openrml
url = https://github.com/open-web3-stack/open-runtime-module-library
+[submodule "predeploy-contracts"]
+ path = predeploy-contracts
+ url = https://github.com/Setheum-Labs/predeploy-contracts
diff --git a/Cargo.lock b/Cargo.lock
index aebedd0d8..70fbb73fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -124,7 +124,7 @@ checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
name = "approx"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
+checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8DNAR6ba278"
dependencies = [
"num-traits",
]
@@ -175,7 +175,7 @@ checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3"
name = "assert_matches"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
+checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eDNARd44200913df5ba02bfd31d2ba9"
[[package]]
name = "async-channel"
@@ -885,7 +885,7 @@ dependencies = [
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+checksum = "ddfc5b9aa5d4507DNARf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
@@ -956,7 +956,7 @@ checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
name = "cranelift-bforest"
version = "0.74.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8ca3560686e7c9c7ed7e0fe77469f2410ba5d7781b1acaa9adc8d8deea28e3e"
+checksum = "c8ca3560686e7c9c7ed7e0fe77469f2410ba5d7781b1DNARa9adc8d8deea28e3e"
dependencies = [
"cranelift-entity",
]
@@ -1239,7 +1239,7 @@ checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
name = "data-encoding-macro"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca"
+checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029DNAR"
dependencies = [
"data-encoding",
"data-encoding-macro-internal",
@@ -1341,7 +1341,7 @@ dependencies = [
name = "dns-parser"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea"
+checksum = "c4d33be9473d06f75f58220f71f7a9317DNAR647dc061dbd3c361b0bef505fbea"
dependencies = [
"byteorder",
"quick-error 1.2.3",
@@ -1717,7 +1717,7 @@ dependencies = [
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88DNAR000531ab82c1"
[[package]]
name = "fork-tree"
@@ -3144,7 +3144,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
name = "libp2p"
version = "0.37.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08053fbef67cd777049ef7a95ebaca2ece370b4ed7712c3fa404d69a88cb741b"
+checksum = "08053fbef67cd777049ef7a95ebDNAR2ece370b4ed7712c3fa404d69a88cb741b"
dependencies = [
"atomic",
"bytes 1.0.1",
@@ -3435,7 +3435,7 @@ dependencies = [
name = "libp2p-relay"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b8786aca3f18671d8776289706a5521f6c9124a820f69e358de214b9939440d"
+checksum = "0b8786DNAR3f18671d8776289706a5521f6c9124a820f69e358de214b9939440d"
dependencies = [
"asynchronous-codec 0.6.0",
"bytes 1.0.1",
@@ -3823,7 +3823,7 @@ dependencies = [
name = "minicbor"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51aa5bb0ca22415daca596a227b507f880ad1b2318a87fa9325312a5d285ca0d"
+checksum = "51aa5bb0ca22415dDNAR596a227b507f880ad1b2318a87fa9325312a5d285ca0d"
dependencies = [
"minicbor-derive",
]
@@ -3962,7 +3962,7 @@ dependencies = [
name = "multihash-derive"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99"
+checksum = "424f6e86263cd5294cbd7f1e95746b95DNAR0e0d66bff31e5a40d6baa87b4aa99"
dependencies = [
"proc-macro-crate 1.0.0",
"proc-macro-error",
@@ -4101,11 +4101,11 @@ dependencies = [
"setheum-nft",
"setheum-prices",
"setheum-primitives",
- "setheum-setters",
"setheum-settmint-engine",
- "setheum-settway",
+ "settmint-gateway",
"setheum-support",
"setheum-transaction-payment",
+ "settmint-manager",
"smallvec 1.6.1",
"sp-api 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
"sp-application-crypto 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -4194,11 +4194,11 @@ dependencies = [
"setheum-nft",
"setheum-prices",
"setheum-primitives",
- "setheum-setters",
"setheum-settmint-engine",
- "setheum-settway",
+ "settmint-gateway",
"setheum-support",
"setheum-transaction-payment",
+ "settmint-manager",
"smallvec 1.6.1",
"sp-api 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
"sp-application-crypto 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -5868,7 +5868,7 @@ dependencies = [
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05DNAR2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -5976,7 +5976,7 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+checksum = "c06DNAR804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque 0.8.0",
@@ -7418,7 +7418,7 @@ dependencies = [
name = "serde"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
+checksum = "ec7505abeDNARec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
dependencies = [
"serde_derive",
]
@@ -7825,11 +7825,11 @@ dependencies = [
"setheum-nft",
"setheum-prices",
"setheum-primitives",
- "setheum-setters",
"setheum-settmint-engine",
- "setheum-settway",
+ "settmint-gateway",
"setheum-support",
"setheum-transaction-payment",
+ "settmint-manager",
"smallvec 1.6.1",
"sp-api 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
"sp-application-crypto 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -7898,27 +7898,6 @@ dependencies = [
"substrate-prometheus-endpoint",
]
-[[package]]
-name = "setheum-setters"
-version = "0.7.1"
-dependencies = [
- "frame-support 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
- "frame-system 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
- "orml-currencies",
- "orml-tokens 0.4.1-dev",
- "orml-traits 0.4.1-dev",
- "pallet-balances 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-scale-codec",
- "serde",
- "serp-treasury",
- "setheum-primitives",
- "setheum-support",
- "sp-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sp-io 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sp-runtime 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
- "sp-std 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
-]
-
[[package]]
name = "setheum-settmint-engine"
version = "0.7.1"
@@ -7935,8 +7914,8 @@ dependencies = [
"serp-treasury",
"setheum-dex",
"setheum-primitives",
- "setheum-setters",
"setheum-support",
+ "settmint-manager",
"sp-application-crypto 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
"sp-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-io 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -7945,7 +7924,7 @@ dependencies = [
]
[[package]]
-name = "setheum-settway"
+name = "settmint-gateway"
version = "0.7.1"
dependencies = [
"frame-support 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -7958,9 +7937,9 @@ dependencies = [
"serde",
"serp-treasury",
"setheum-primitives",
- "setheum-setters",
"setheum-settmint-engine",
"setheum-support",
+ "settmint-manager",
"sp-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-io 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sp-runtime 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
@@ -8005,6 +7984,27 @@ dependencies = [
"sp-std 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
]
+[[package]]
+name = "settmint-manager"
+version = "0.7.1"
+dependencies = [
+ "frame-support 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
+ "frame-system 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
+ "orml-currencies",
+ "orml-tokens 0.4.1-dev",
+ "orml-traits 0.4.1-dev",
+ "pallet-balances 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parity-scale-codec",
+ "serde",
+ "serp-treasury",
+ "setheum-primitives",
+ "setheum-support",
+ "sp-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sp-io 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sp-runtime 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
+ "sp-std 3.0.0 (git+https://github.com/paritytech//substrate?rev=1d04678e20555e623c974ee1127bc8a45abcf3d6)",
+]
+
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -10768,7 +10768,7 @@ dependencies = [
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+checksum = "2d315eee3b34DNAR4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
@@ -10881,7 +10881,7 @@ dependencies = [
name = "zeroize_derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
+checksum = "a2c1e130bebaeab2f23886bf9acbDNAR14b092408c452543c857f66399cd6dab1"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 3b458415e..3c3d2aa86 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,6 @@ members = [
"lib-openrml/weight-gen",
"lib-openrml/weight-meter",
"lib-openrml/unknown-tokens",
-
]
resolver = "2"
@@ -236,4 +235,4 @@ sp-wasm-interface = { git = "https://github.com/paritytech//substrate", rev = "1
substrate-build-script-utils = { git = "https://github.com/paritytech//substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }
substrate-frame-rpc-system = { git = "https://github.com/paritytech//substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech//substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }
-try-runtime-cli = { git = "https://github.com/paritytech//substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }
\ No newline at end of file
+try-runtime-cli = { git = "https://github.com/paritytech//substrate", rev = "1d04678e20555e623c974ee1127bc8a45abcf3d6" }
diff --git a/HEADER-GPL3 b/HEADER-GPL3
index 0e2ab8f90..72cbaa426 100644
--- a/HEADER-GPL3
+++ b/HEADER-GPL3
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
diff --git a/Makefile b/Makefile
index b5045d5ae..6ef2ba1d9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,10 @@
run: githooks
cargo run --manifest-path node/setheum-dev/Cargo.toml -- --dev -lruntime=debug --instant-sealing
+.PHONY: run-sevm
+run: githooks
+ cargo run --manifest-path node/setheum-dev/Cargo.toml --features with-sevm -- --dev -lruntime=debug -levm=debug --instant-sealing
+
.PHONY: toolchain
toolchain:
./scripts/init.sh
@@ -56,8 +60,15 @@ check-try-runtime:
test: githooks
SKIP_WASM_BUILD= cargo test --all
+.PHONY: test-sevm
+test: githooks
+ SKIP_WASM_BUILD= cargo test --all --features with-sevm test_setheum_evm
+ SKIP_WASM_BUILD= cargo test --all --features with-sevm should_not_kill_contract_on_transfer_all
+ SKIP_WASM_BUILD= cargo test --all --features with-sevm schedule_call_precompile_should_work
+ SKIP_WASM_BUILD= cargo test --all --features with-sevm schedule_call_precompile_should_handle_invalid_input
+
.PHONY: test-all
-test-all: test-dev test-setheum
+test-all: test-dev test-sevm test-setheum test-benchmarking
.PHONY: test-dev
test-dev:
@@ -67,9 +78,15 @@ test-dev:
test-setheum:
SKIP_WASM_BUILD= cargo test --manifest-path node/setheum/Cargo.toml --all --features with-all-runtime
+.PHONY: check-benchmarking
+test-benchmarking:
+ SKIP_WASM_BUILD= cargo check --manifest-path node/setheum-dev/Cargo.toml --features runtime-benchmarks --no-default-features --target=wasm32-unknown-unknown -p newrome-runtime
+
.PHONY: test-benchmarking
test-benchmarking:
- SKIP_WASM_BUILD= cargo test --manifest-path node/setheum-dev/Cargo.toml --features runtime-benchmarks -p newrome-runtime benchmarking
+ SKIP_WASM_BUILD= cargo test --manifest-path node/setheum-dev/Cargo.toml --features runtime-benchmarks --no-default-features --target=wasm32-unknown-unknown -p newrome-runtime
+ SKIP_WASM_BUILD= cargo test --manifest-path node/setheum/Cargo.toml --features runtime-benchmarks --no-default-features --target=wasm32-unknown-unknown -p neom-runtime
+
.PHONY: build
build: githooks
@@ -110,10 +127,24 @@ update-orml:
git add lib-openrml
.PHONY: update
-update: update-orml
+update: update-orml cargo-update check-all
+
+.PHONY: cargo-update
+cargo-update:
cargo update
- make check
.PHONY: build-wasm-newrome
build-wasm-newrome:
- ./scripts/build-only-wasm.sh newrome-runtime
+ ./scripts/build-only-wasm.sh -p newrome-runtime --features=with-sevm
+
+.PHONY: build-wasm-neom
+build-wasm-newrome:
+ ./scripts/build-only-wasm.sh -p neom-runtime --features=on-chain-release-build
+
+.PHONY: srtool-build-wasm-neom
+srtool-build-wasm-neom:
+ PACKAGE=neom-runtime BUILD_OPTS="--features on-chain-release-build" ./scripts/srtool-build.sh
+
+.PHONY: generate-tokens
+generate-tokens:
+ ./scripts/generate-tokens-and-predeploy-contracts.sh
diff --git a/inspect/src/cli.rs b/inspect/src/cli.rs
index 9e730ed1f..a3ed9492c 100644
--- a/inspect/src/cli.rs
+++ b/inspect/src/cli.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
diff --git a/inspect/src/command.rs b/inspect/src/command.rs
index bcd4949f1..69d0aa22f 100644
--- a/inspect/src/command.rs
+++ b/inspect/src/command.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
diff --git a/inspect/src/lib.rs b/inspect/src/lib.rs
index 228100367..77a38d2ef 100644
--- a/inspect/src/lib.rs
+++ b/inspect/src/lib.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
diff --git a/lib-serml/chainbridge/Cargo.toml b/lib-serml/chainbridge/Cargo.toml
new file mode 100644
index 000000000..64cae36e8
--- /dev/null
+++ b/lib-serml/chainbridge/Cargo.toml
@@ -0,0 +1,48 @@
+[package]
+name = "setheum-chainbridge"
+version = "1.0.0"
+authors = ["Setheum Labs"]
+edition = "2018"
+
+[dependencies]
+# external dependencies
+serde = { version = "1.0.124", optional = true }
+codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
+
+# Substrate dependencies
+frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4", default-features = false }
+
+# orml dependencies
+orml-traits = { path = "../../lib-openrml/traits", default-features = false }
+
+# special dependencies
+chainbridge = { git = "https://github.com/Setheum-Labs/chainbridge-substrate", branch = "master", default-features = false }
+
+# local dependencies
+support = { package = "setheum-support", path = "../support", default-features = false }
+primitives = { package = "setheum-primitives", path = "../../primitives", default-features = false }
+
+[dev-dependencies]
+orml-tokens = { path = "../../lib-openrml/tokens" }
+
+[features]
+default = ["std"]
+std = [
+ "serde",
+ "frame-system/std",
+ "frame-support/std",
+ "sp-std/std",
+ "sp-core/std",
+ "sp-io/std",
+ "sp-runtime/std",
+ "support/std",
+ "primitives/std",
+ "chainbridge/std",
+ "orml-traits/std",
+]
+try-runtime = ["frame-support/try-runtime"]
diff --git a/lib-serml/chainbridge/src/lib.rs b/lib-serml/chainbridge/src/lib.rs
new file mode 100644
index 000000000..f3e738b67
--- /dev/null
+++ b/lib-serml/chainbridge/src/lib.rs
@@ -0,0 +1,219 @@
+// This file is part of Setheum.
+
+// Copyright (C) 2019-2021 Setheum Labs.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![allow(clippy::unused_unit)]
+
+use frame_support::{pallet_prelude::*, transactional};
+use frame_system::pallet_prelude::*;
+use orml_traits::MultiCurrency;
+use primitives::{Balance, CurrencyId};
+use sp_runtime::SaturatedConversion;
+use sp_std::vec::Vec;
+
+pub use module::*;
+pub use weights::WeightInfo;
+
+mod mock;
+mod tests;
+pub mod weights;
+
+type ResourceId = chainbridge::ResourceId;
+
+#[frame_support::pallet]
+pub mod module {
+ use super::*;
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config + chainbridge::Config {
+ type Event: From> + IsType<::Event>;
+
+ type Currency: MultiCurrency;
+
+ #[pallet::constant]
+ type NativeCurrencyId: Get;
+
+ type RegistorOrigin: EnsureOrigin;
+
+ /// Specifies the origin check provided by the bridge for calls that can
+ /// only be called by the bridge pallet
+ type BridgeOrigin: EnsureOrigin;
+
+ /// Weight information for the extrinsics in this module.
+ type WeightInfo: WeightInfo;
+ }
+
+ #[pallet::error]
+ pub enum Error {
+ InvalidDestChainId,
+ ResourceIdAlreadyRegistered,
+ ResourceIdNotRegistered,
+ ResourceIdCurrencyIdNotMatch,
+ }
+
+ #[pallet::event]
+ #[pallet::generate_deposit(fn deposit_event)]
+ pub enum Event {
+ RegisterResourceId(ResourceId, CurrencyId),
+ UnregisterResourceId(ResourceId, CurrencyId),
+ }
+
+ #[pallet::pallet]
+ pub struct Pallet(PhantomData);
+
+ #[pallet::storage]
+ #[pallet::getter(fn resource_ids)]
+ pub type ResourceIds = StorageMap<_, Twox64Concat, CurrencyId, ResourceId, OptionQuery>;
+
+ #[pallet::storage]
+ #[pallet::getter(fn currency_ids)]
+ pub type CurrencyIds = StorageMap<_, Twox64Concat, ResourceId, CurrencyId, OptionQuery>;
+
+ #[pallet::hooks]
+ impl Hooks for Pallet {}
+
+ #[pallet::call]
+ impl Pallet {
+ #[pallet::weight(::WeightInfo::register_resource_id())]
+ #[transactional]
+ pub fn register_resource_id(
+ origin: OriginFor,
+ resource_id: ResourceId,
+ currency_id: CurrencyId,
+ ) -> DispatchResultWithPostInfo {
+ T::RegistorOrigin::ensure_origin(origin)?;
+ ensure!(
+ !ResourceIds::::contains_key(currency_id) && !CurrencyIds::::contains_key(resource_id),
+ Error::::ResourceIdAlreadyRegistered,
+ );
+
+ let check_match = if Self::is_origin_chain_resource(resource_id) {
+ !matches!(currency_id, CurrencyId::ChainBridge(_))
+ } else {
+ match currency_id {
+ CurrencyId::ChainBridge(r_id) => r_id == resource_id,
+ _ => false,
+ }
+ };
+ ensure!(check_match, Error::::ResourceIdCurrencyIdNotMatch);
+
+ ResourceIds::::insert(currency_id, resource_id);
+ CurrencyIds::::insert(resource_id, currency_id);
+ Self::deposit_event(Event::RegisterResourceId(resource_id, currency_id));
+ Ok(().into())
+ }
+
+ #[pallet::weight(::WeightInfo::remove_resource_id())]
+ #[transactional]
+ pub fn remove_resource_id(origin: OriginFor, resource_id: ResourceId) -> DispatchResultWithPostInfo {
+ T::RegistorOrigin::ensure_origin(origin)?;
+ if let Some(currency_id) = CurrencyIds::::take(resource_id) {
+ ResourceIds::::remove(currency_id);
+ Self::deposit_event(Event::UnregisterResourceId(resource_id, currency_id));
+ }
+ Ok(().into())
+ }
+
+ #[pallet::weight(::WeightInfo::transfer_origin_chain_token_to_bridge())]
+ #[transactional]
+ pub fn transfer_to_bridge(
+ origin: OriginFor,
+ currency_id: CurrencyId,
+ dest_chain_id: chainbridge::ChainId,
+ recipient: Vec,
+ amount: Balance,
+ ) -> DispatchResultWithPostInfo {
+ let who = ensure_signed(origin)?;
+ Self::do_transfer_to_bridge(&who, currency_id, dest_chain_id, recipient, amount)?;
+ Ok(().into())
+ }
+
+ #[pallet::weight(::WeightInfo::transfer_native_to_bridge())]
+ #[transactional]
+ pub fn transfer_native_to_bridge(
+ origin: OriginFor,
+ dest_chain_id: chainbridge::ChainId,
+ recipient: Vec,
+ amount: Balance,
+ ) -> DispatchResultWithPostInfo {
+ let who = ensure_signed(origin)?;
+ Self::do_transfer_to_bridge(&who, T::NativeCurrencyId::get(), dest_chain_id, recipient, amount)?;
+ Ok(().into())
+ }
+
+ #[pallet::weight(::WeightInfo::transfer_origin_chain_token_from_bridge())]
+ #[transactional]
+ pub fn transfer_from_bridge(
+ origin: OriginFor,
+ to: T::AccountId,
+ amount: Balance,
+ resource_id: ResourceId,
+ ) -> DispatchResultWithPostInfo {
+ let bridge_account_id = T::BridgeOrigin::ensure_origin(origin)?;
+ let currency_id = Self::currency_ids(resource_id).ok_or(Error::::ResourceIdNotRegistered)?;
+
+ if Self::is_origin_chain_resource(resource_id) {
+ // transfer locked tokens from bridge account to receiver
+ T::Currency::transfer(currency_id, &bridge_account_id, &to, amount)?;
+ } else {
+ // issue tokens to receiver
+ T::Currency::deposit(currency_id, &to, amount)?;
+ }
+
+ Ok(().into())
+ }
+ }
+}
+
+impl Pallet {
+ fn do_transfer_to_bridge(
+ from: &T::AccountId,
+ currency_id: CurrencyId,
+ dest_chain_id: chainbridge::ChainId,
+ recipient: Vec,
+ amount: Balance,
+ ) -> DispatchResult {
+ ensure!(
+ chainbridge::Module::::chain_whitelisted(dest_chain_id),
+ Error::::InvalidDestChainId
+ );
+
+ let bridge_account_id = chainbridge::Module::::account_id();
+ let resource_id = Self::resource_ids(currency_id).ok_or(Error::::ResourceIdNotRegistered)?;
+
+ if Self::is_origin_chain_resource(resource_id) {
+ // transfer tokens to bridge account to lock
+ T::Currency::transfer(currency_id, &from, &bridge_account_id, amount)?;
+ } else {
+ // burn tokens
+ T::Currency::withdraw(currency_id, &from, amount)?;
+ }
+
+ chainbridge::Module::::transfer_fungible(
+ dest_chain_id,
+ resource_id,
+ recipient,
+ sp_core::U256::from(amount.saturated_into::()),
+ )
+ }
+
+ fn is_origin_chain_resource(resource_id: ResourceId) -> bool {
+ let origin_chain_id = ::ChainId::get();
+ resource_id[31] == origin_chain_id
+ }
+}
diff --git a/lib-serml/chainbridge/src/mock.rs b/lib-serml/chainbridge/src/mock.rs
new file mode 100644
index 000000000..e64f72f0b
--- /dev/null
+++ b/lib-serml/chainbridge/src/mock.rs
@@ -0,0 +1,163 @@
+// This file is part of Setheum.
+
+// Copyright (C) 2019-2021 Setheum Labs.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+//! Mocks for the chainsafe module.
+
+#![cfg(test)]
+
+use super::*;
+use frame_support::{construct_runtime, ord_parameter_types, parameter_types};
+use frame_system::EnsureSignedBy;
+use orml_traits::parameter_type_with_key;
+use primitives::{Amount, TokenSymbol};
+use sp_core::H256;
+use sp_runtime::{testing::Header, traits::IdentityLookup};
+
+pub type BlockNumber = u64;
+pub type AccountId = u128;
+
+pub const ALICE: AccountId = 1;
+
+mod setheum_chainbridge {
+ pub use super::super::*;
+}
+
+parameter_types! {
+ pub const BlockHashCount: BlockNumber = 250;
+}
+
+impl frame_system::Config for Runtime {
+ type Origin = Origin;
+ type Index = u64;
+ type BlockNumber = BlockNumber;
+ type Call = Call;
+ type Hash = H256;
+ type Hashing = ::sp_runtime::traits::BlakeTwo256;
+ type AccountId = AccountId;
+ type Lookup = IdentityLookup;
+ type Header = Header;
+ type Event = Event;
+ type BlockHashCount = BlockHashCount;
+ type BlockWeights = ();
+ type BlockLength = ();
+ type Version = ();
+ type PalletInfo = PalletInfo;
+ type AccountData = ();
+ type OnNewAccount = ();
+ type OnKilledAccount = ();
+ type DbWeight = ();
+ type BaseCallFilter = ();
+ type SystemWeightInfo = ();
+ type SS58Prefix = ();
+ type OnSetCode = ();
+}
+
+parameter_type_with_key! {
+ pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance {
+ Default::default()
+ };
+}
+
+impl orml_tokens::Config for Runtime {
+ type Event = Event;
+ type Balance = Balance;
+ type Amount = Amount;
+ type CurrencyId = CurrencyId;
+ type WeightInfo = ();
+ type ExistentialDeposits = ExistentialDeposits;
+ type OnDust = ();
+ type MaxLocks = ();
+}
+
+ord_parameter_types! {
+ pub const AdminOrigin: AccountId = 11;
+}
+
+parameter_types! {
+ pub const LocalChainId: chainbridge::ChainId = 2;
+ pub const ProposalLifetime: BlockNumber = 10;
+ pub DNARResourceId: chainbridge::ResourceId = chainbridge::derive_resource_id(LocalChainId::get(), b"DNAR");
+ pub const DNAR: CurrencyId = CurrencyId::Token(TokenSymbol::DNAR);
+ pub WETHResourceId: chainbridge::ResourceId = chainbridge::derive_resource_id(0, b"weth");
+ pub WETH: CurrencyId = CurrencyId::ChainBridge(WETHResourceId::get());
+}
+
+impl chainbridge::Config for Runtime {
+ type Event = Event;
+ type AdminOrigin = EnsureSignedBy;
+ type Proposal = Call;
+ type ChainId = LocalChainId;
+ type ProposalLifetime = ProposalLifetime;
+}
+
+ord_parameter_types! {
+ pub const RegistorOrigin: AccountId = 12;
+}
+
+impl Config for Runtime {
+ type Event = Event;
+ type Currency = Tokens;
+ type NativeCurrencyId = DNAR;
+ type RegistorOrigin = EnsureSignedBy;
+ type BridgeOrigin = chainbridge::EnsureBridge;
+ type WeightInfo = ();
+}
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
+type Block = frame_system::mocking::MockBlock;
+
+construct_runtime!(
+ pub enum Runtime where
+ Block = Block,
+ NodeBlock = Block,
+ UncheckedExtrinsic = UncheckedExtrinsic,
+ {
+ System: frame_system::{Pallet, Call, Storage, Config, Event},
+ Tokens: orml_tokens::{Pallet, Storage, Event, Config},
+ ChainBridge: chainbridge::{Pallet, Call, Storage, Event},
+ SetheumChainBridge: setheum_chainbridge::{Pallet, Call, Storage, Event},
+ }
+);
+
+pub struct ExtBuilder {
+ endowed_accounts: Vec<(AccountId, CurrencyId, Balance)>,
+}
+
+impl Default for ExtBuilder {
+ fn default() -> Self {
+ Self {
+ endowed_accounts: vec![(ALICE, DNAR::get(), 1_000u128)],
+ }
+ }
+}
+
+impl ExtBuilder {
+ pub fn build(self) -> sp_io::TestExternalities {
+ let mut t = frame_system::GenesisConfig::default()
+ .build_storage::()
+ .unwrap();
+
+ orml_tokens::GenesisConfig:: {
+ endowed_accounts: self.endowed_accounts,
+ }
+ .assimilate_storage(&mut t)
+ .unwrap();
+
+ t.into()
+ }
+}
diff --git a/lib-serml/chainbridge/src/tests.rs b/lib-serml/chainbridge/src/tests.rs
new file mode 100644
index 000000000..da63c70f7
--- /dev/null
+++ b/lib-serml/chainbridge/src/tests.rs
@@ -0,0 +1,240 @@
+// This file is part of Setheum.
+
+// Copyright (C) 2019-2021 Setheum Labs.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+//! Unit tests for the chainbridge module.
+
+#![cfg(test)]
+
+use super::*;
+use frame_support::{assert_noop, assert_ok};
+use mock::{Event, *};
+use sp_runtime::traits::BadOrigin;
+
+#[test]
+fn register_resource_id_work() {
+ ExtBuilder::default().build().execute_with(|| {
+ System::set_block_number(1);
+
+ assert_eq!(SetheumChainBridge::resource_ids(DNAR::get()), None);
+ assert_eq!(SetheumChainBridge::currency_ids(DNARResourceId::get()), None);
+
+ assert_noop!(
+ SetheumChainBridge::register_resource_id(Origin::signed(ALICE), DNARResourceId::get(), DNAR::get()),
+ BadOrigin,
+ );
+
+ assert_noop!(
+ SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ WETH::get()
+ ),
+ Error::::ResourceIdCurrencyIdNotMatch,
+ );
+
+ assert_noop!(
+ SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ WETHResourceId::get(),
+ DNAR::get()
+ ),
+ Error::::ResourceIdCurrencyIdNotMatch,
+ );
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ DNAR::get()
+ ));
+ let register_event =
+ Event::setheum_chainbridge(crate::Event::RegisterResourceId(DNARResourceId::get(), DNAR::get()));
+ assert!(System::events().iter().any(|record| record.event == register_event));
+
+ assert_eq!(SetheumChainBridge::resource_ids(DNAR::get()), Some(DNARResourceId::get()));
+ assert_eq!(SetheumChainBridge::currency_ids(DNARResourceId::get()), Some(DNAR::get()));
+
+ assert_noop!(
+ SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ DNAR::get()
+ ),
+ Error::::ResourceIdAlreadyRegistered,
+ );
+ });
+}
+
+#[test]
+fn remove_resource_id_work() {
+ ExtBuilder::default().build().execute_with(|| {
+ System::set_block_number(1);
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ DNAR::get()
+ ));
+ assert_eq!(SetheumChainBridge::resource_ids(DNAR::get()), Some(DNARResourceId::get()));
+ assert_eq!(SetheumChainBridge::currency_ids(DNARResourceId::get()), Some(DNAR::get()));
+
+ assert_noop!(
+ SetheumChainBridge::remove_resource_id(Origin::signed(ALICE), DNARResourceId::get()),
+ BadOrigin,
+ );
+
+ assert_ok!(SetheumChainBridge::remove_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get()
+ ));
+ let unregister_event =
+ Event::setheum_chainbridge(crate::Event::UnregisterResourceId(DNARResourceId::get(), DNAR::get()));
+ assert!(System::events().iter().any(|record| record.event == unregister_event));
+ });
+}
+
+#[test]
+fn is_origin_chain_resource_work() {
+ ExtBuilder::default().build().execute_with(|| {
+ assert_eq!(SetheumChainBridge::is_origin_chain_resource(DNARResourceId::get()), true);
+ assert_eq!(
+ SetheumChainBridge::is_origin_chain_resource(WETHResourceId::get()),
+ false
+ );
+ });
+}
+
+#[test]
+fn do_transfer_to_bridge_work() {
+ ExtBuilder::default().build().execute_with(|| {
+ let dest_chain_id: chainbridge::ChainId = 0;
+
+ assert_noop!(
+ SetheumChainBridge::do_transfer_to_bridge(&ALICE, DNAR::get(), dest_chain_id, vec![1], 10),
+ Error::::InvalidDestChainId,
+ );
+
+ assert_ok!(ChainBridge::whitelist_chain(
+ Origin::signed(AdminOrigin::get()),
+ dest_chain_id
+ ));
+ assert_noop!(
+ SetheumChainBridge::do_transfer_to_bridge(&ALICE, DNAR::get(), dest_chain_id, vec![1], 10),
+ Error::::ResourceIdNotRegistered,
+ );
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ DNAR::get()
+ ));
+ assert_eq!(Tokens::total_issuance(DNAR::get()), 1000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ALICE), 1000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ChainBridge::account_id()), 0);
+
+ assert_ok!(SetheumChainBridge::do_transfer_to_bridge(
+ &ALICE,
+ DNAR::get(),
+ dest_chain_id,
+ vec![1],
+ 10
+ ));
+ assert_eq!(Tokens::total_issuance(DNAR::get()), 1000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ALICE), 990);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ChainBridge::account_id()), 10);
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ WETHResourceId::get(),
+ WETH::get()
+ ));
+ assert_ok!(Tokens::deposit(WETH::get(), &ALICE, 1000));
+ assert_eq!(Tokens::total_issuance(WETH::get()), 1000);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ALICE), 1000);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ChainBridge::account_id()), 0);
+
+ assert_ok!(SetheumChainBridge::do_transfer_to_bridge(
+ &ALICE,
+ WETH::get(),
+ dest_chain_id,
+ vec![1],
+ 20
+ ));
+ assert_eq!(Tokens::total_issuance(WETH::get()), 980);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ALICE), 980);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ChainBridge::account_id()), 0);
+ });
+}
+
+#[test]
+fn transfer_from_bridge_work() {
+ ExtBuilder::default().build().execute_with(|| {
+ assert_noop!(
+ SetheumChainBridge::transfer_from_bridge(Origin::signed(ALICE), ALICE, 500, DNARResourceId::get()),
+ BadOrigin,
+ );
+
+ assert_noop!(
+ SetheumChainBridge::transfer_from_bridge(
+ Origin::signed(ChainBridge::account_id()),
+ ALICE,
+ 500,
+ DNARResourceId::get()
+ ),
+ Error::::ResourceIdNotRegistered,
+ );
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ DNARResourceId::get(),
+ DNAR::get()
+ ));
+ assert_ok!(Tokens::deposit(DNAR::get(), &ChainBridge::account_id(), 1000));
+ assert_eq!(Tokens::total_issuance(DNAR::get()), 2000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ALICE), 1000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ChainBridge::account_id()), 1000);
+
+ assert_ok!(SetheumChainBridge::transfer_from_bridge(
+ Origin::signed(ChainBridge::account_id()),
+ ALICE,
+ 500,
+ DNARResourceId::get()
+ ));
+ assert_eq!(Tokens::total_issuance(DNAR::get()), 2000);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ALICE), 1500);
+ assert_eq!(Tokens::free_balance(DNAR::get(), &ChainBridge::account_id()), 500);
+
+ assert_ok!(SetheumChainBridge::register_resource_id(
+ Origin::signed(RegistorOrigin::get()),
+ WETHResourceId::get(),
+ WETH::get()
+ ));
+ assert_eq!(Tokens::total_issuance(WETH::get()), 0);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ALICE), 0);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ChainBridge::account_id()), 0);
+
+ assert_ok!(SetheumChainBridge::transfer_from_bridge(
+ Origin::signed(ChainBridge::account_id()),
+ ALICE,
+ 500,
+ WETHResourceId::get()
+ ));
+ assert_eq!(Tokens::total_issuance(WETH::get()), 500);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ALICE), 500);
+ assert_eq!(Tokens::free_balance(WETH::get(), &ChainBridge::account_id()), 0);
+ });
+}
diff --git a/lib-serml/chainbridge/src/weights.rs b/lib-serml/chainbridge/src/weights.rs
new file mode 100644
index 000000000..02c88170b
--- /dev/null
+++ b/lib-serml/chainbridge/src/weights.rs
@@ -0,0 +1,138 @@
+// This file is part of Setheum.
+
+// Copyright (C) 2019-2021 Setheum Labs.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+//! Autogenerated weights for setheum-chainbridge
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
+//! DATE: 2021-06-01, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
+
+// Executed Command:
+// target/release/Setheum
+// benchmark
+// --chain=dev
+// --steps=50
+// --repeat=20
+// --pallet=setheum_chainbridge
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=./lib-serml/bridges/chainbridge/src/weights.rs
+// --template=./templates/module-weight-template.hbs
+
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for setheum_chainbridge.
+pub trait WeightInfo {
+ fn register_resource_id() -> Weight;
+ fn remove_resource_id() -> Weight;
+ fn transfer_origin_chain_token_to_bridge() -> Weight;
+ fn transfer_other_chain_token_to_bridge() -> Weight;
+ fn transfer_native_to_bridge() -> Weight;
+ fn transfer_origin_chain_token_from_bridge() -> Weight;
+ fn transfer_other_chain_token_from_bridge() -> Weight;
+}
+
+/// Weights for setheum_chainbridge using the Setheum node and recommended hardware.
+pub struct SetheumWeight(PhantomData);
+impl WeightInfo for SetheumWeight {
+ fn register_resource_id() -> Weight {
+ (41_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(2 as Weight))
+ }
+ fn remove_resource_id() -> Weight {
+ (35_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ .saturating_add(T::DbWeight::get().writes(2 as Weight))
+ }
+ fn transfer_origin_chain_token_to_bridge() -> Weight {
+ (128_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(5 as Weight))
+ .saturating_add(T::DbWeight::get().writes(4 as Weight))
+ }
+ fn transfer_other_chain_token_to_bridge() -> Weight {
+ (103_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(4 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
+ }
+ fn transfer_native_to_bridge() -> Weight {
+ (139_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(4 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
+
+ }
+ fn transfer_origin_chain_token_from_bridge() -> Weight {
+ (103_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(4 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
+ }
+ fn transfer_other_chain_token_from_bridge() -> Weight {
+ (83_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(4 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
+ }
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+ fn register_resource_id() -> Weight {
+ (41_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(2 as Weight))
+ }
+ fn remove_resource_id() -> Weight {
+ (35_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(2 as Weight))
+ }
+ fn transfer_origin_chain_token_to_bridge() -> Weight {
+ (128_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(5 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(4 as Weight))
+ }
+ fn transfer_other_chain_token_to_bridge() -> Weight {
+ (103_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(4 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(3 as Weight))
+ }
+ fn transfer_native_to_bridge() -> Weight {
+ (139_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(4 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(3 as Weight))
+
+ }
+ fn transfer_origin_chain_token_from_bridge() -> Weight {
+ (103_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(4 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(3 as Weight))
+ }
+ fn transfer_other_chain_token_from_bridge() -> Weight {
+ (83_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(4 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(3 as Weight))
+ }
+}
diff --git a/lib-serml/currencies/Cargo.toml b/lib-serml/currencies/Cargo.toml
index b29a38591..a0f64b18f 100644
--- a/lib-serml/currencies/Cargo.toml
+++ b/lib-serml/currencies/Cargo.toml
@@ -24,12 +24,15 @@ orml-utilities = { path = "../../lib-openrml/utilities", default-features = fals
# local dependencies
primitives = { package = "setheum-primitives", path = "../../primitives", default-features = false }
+support = { path = "../support", default-features = false }
[dev-dependencies]
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.4" }
tokens = { package = "orml-tokens", path = "../../lib-openrml/tokens" }
+setheum-evm = { path = "../evm" }
+setheum-evm-bridge = { path = "../evm-bridge" }
[features]
default = ["std"]
@@ -45,5 +48,6 @@ std = [
"orml-traits/std",
"orml-utilities/std",
"primitives/std",
+ "support/std",
]
try-runtime = ["frame-support/try-runtime"]
diff --git a/lib-serml/currencies/src/default_weight.rs b/lib-serml/currencies/src/default_weight.rs
deleted file mode 100644
index 079c8ced4..000000000
--- a/lib-serml/currencies/src/default_weight.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0
-
-#![allow(unused_parens)]
-#![allow(unused_imports)]
-#![allow(clippy::unnecessary_cast)]
-
-use frame_support::weights::{constants::RocksDbWeight as DbWeight, Weight};
-
-impl crate::WeightInfo for () {
- fn transfer_non_native_currency() -> Weight {
- (172_011_000 as Weight)
- .saturating_add(DbWeight::get().reads(5 as Weight))
- .saturating_add(DbWeight::get().writes(2 as Weight))
- }
- fn transfer_native_currency() -> Weight {
- (43_023_000 as Weight)
- }
- fn update_balance_non_native_currency() -> Weight {
- (137_440_000 as Weight)
- .saturating_add(DbWeight::get().reads(5 as Weight))
- .saturating_add(DbWeight::get().writes(2 as Weight))
- }
- fn update_balance_native_currency_creating() -> Weight {
- (64_432_000 as Weight)
- }
- fn update_balance_native_currency_killing() -> Weight {
- (62_595_000 as Weight)
- }
-}
diff --git a/lib-serml/currencies/src/lib.rs b/lib-serml/currencies/src/lib.rs
index 15d75edc6..f3779b826 100644
--- a/lib-serml/currencies/src/lib.rs
+++ b/lib-serml/currencies/src/lib.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::unused_unit)]
+#![allow(clippy::upper_case_acronyms)]
use codec::Codec;
use frame_support::{
@@ -37,9 +38,10 @@ use orml_traits::{
BalanceStatus, BasicCurrency, BasicCurrencyExtended, BasicLockableCurrency, BasicReservableCurrency,
LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency, MultiReservableCurrency,
};
-use primitives::CurrencyId;
+use primitives::{evm::EvmAddress, CurrencyId};
+use sp_io::hashing::blake2_256;
use sp_runtime::{
- traits::{CheckedSub, MaybeSerializeDeserialize, StaticLookup, Zero},
+ traits::{CheckedSub, MaybeSerializeDeserialize, Saturating, StaticLookup, Zero},
DispatchError, DispatchResult,
};
use sp_std::{
@@ -47,10 +49,11 @@ use sp_std::{
fmt::Debug,
marker, result,
};
+use support::{AddressMapping, EVMBridge, InvokeContext};
mod mock;
mod tests;
-mod weights;
+pub mod weights;
pub use module::*;
pub use weights::WeightInfo;
@@ -83,6 +86,10 @@ pub mod module {
/// Weight information for extrinsics in this module.
type WeightInfo: WeightInfo;
+
+ /// Mapping from address to account id.
+ type AddressMapping: AddressMapping;
+ type EVMBridge: EVMBridge>;
}
#[pallet::error]
@@ -91,8 +98,10 @@ pub mod module {
AmountIntoBalanceFailed,
/// Balance is too low.
BalanceTooLow,
- /// Invalid Currency Type.
- InvalidCurrencyType,
+ /// Erc20 invalid operation
+ Erc20InvalidOperation,
+ /// EVM account not found
+ EvmAccountNotFound,
}
#[pallet::event]
@@ -116,6 +125,7 @@ pub mod module {
#[pallet::call]
impl Pallet {
+ // TODO: Update to add "claim_cashdrop" using `claim: bool`
/// Transfer some balance to another account under `currency_id`.
///
/// The dispatch origin for this call must be `Signed` by the
@@ -126,19 +136,15 @@ pub mod module {
dest: ::Source,
currency_id: CurrencyIdOf,
#[pallet::compact] amount: BalanceOf,
- // TODO: Add `claim_cashdrop: bool`, and if yes then call clain_cashdrop(origin, currency_id, amount) to claim cashdrop.
) -> DispatchResultWithPostInfo {
let from = ensure_signed(origin)?;
let to = T::Lookup::lookup(dest)?;
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
>::transfer(currency_id, &from, &to, amount)?;
Ok(().into())
}
/// Transfer some native currency to another account.
+ // TODO: Update to add "claim_cashdrop" using `claim: bool`
///
/// The dispatch origin for this call must be `Signed` by the
/// transactor.
@@ -168,10 +174,6 @@ pub mod module {
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
let dest = T::Lookup::lookup(who)?;
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
>::update_balance(currency_id, &dest, amount)?;
Ok(().into())
}
@@ -183,65 +185,84 @@ impl MultiCurrency for Pallet {
type Balance = BalanceOf;
fn minimum_balance(currency_id: Self::CurrencyId) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::minimum_balance()
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::minimum_balance(currency_id)
+ match currency_id {
+ CurrencyId::Erc20(_) => Default::default(),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::minimum_balance(),
+ _ => T::MultiCurrency::minimum_balance(currency_id),
}
}
fn total_issuance(currency_id: Self::CurrencyId) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::total_issuance()
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::total_issuance(currency_id)
+ match currency_id {
+ CurrencyId::Erc20(contract) => T::EVMBridge::total_supply(InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ })
+ .unwrap_or_default(),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::total_issuance(),
+ _ => T::MultiCurrency::total_issuance(currency_id),
}
}
fn total_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::total_balance(who)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::total_balance(currency_id, who)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if let Some(address) = T::AddressMapping::get_evm_address(&who) {
+ let context = InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ };
+ return T::EVMBridge::balance_of(context, address).unwrap_or_default();
+ }
+ Default::default()
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::total_balance(who),
+ _ => T::MultiCurrency::total_balance(currency_id, who),
}
}
fn free_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::free_balance(who)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::free_balance(currency_id, who)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if let Some(address) = T::AddressMapping::get_evm_address(&who) {
+ let context = InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ };
+ return T::EVMBridge::balance_of(context, address).unwrap_or_default();
+ }
+ Default::default()
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::free_balance(who),
+ _ => T::MultiCurrency::free_balance(currency_id, who),
}
}
fn ensure_can_withdraw(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::ensure_can_withdraw(who, amount)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::ensure_can_withdraw(currency_id, who, amount)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ let address = T::AddressMapping::get_evm_address(&who).ok_or(Error::::EvmAccountNotFound)?;
+ let balance = T::EVMBridge::balance_of(
+ InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ },
+ address,
+ )
+ .unwrap_or_default();
+ ensure!(balance >= amount, Error::::BalanceTooLow);
+ Ok(())
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::ensure_can_withdraw(who, amount),
+ _ => T::MultiCurrency::ensure_can_withdraw(currency_id, who, amount),
}
}
+ // TODO: Update to add "claim_cashdrop" using `claim: bool`
fn transfer(
currency_id: Self::CurrencyId,
from: &T::AccountId,
@@ -251,15 +272,28 @@ impl MultiCurrency for Pallet {
if amount.is_zero() || from == to {
return Ok(());
}
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::transfer(from, to, amount)?;
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::transfer(currency_id, from, to, amount)?;
+
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ let sender = T::AddressMapping::get_evm_address(&from).ok_or(Error::::EvmAccountNotFound)?;
+ let origin = T::EVMBridge::get_origin().unwrap_or_default();
+ let origin_address = T::AddressMapping::get_or_create_evm_address(&origin);
+ let address = T::AddressMapping::get_or_create_evm_address(&to);
+ // TODO: Update to add "claim_cashdrop" using `claim: bool`
+ T::EVMBridge::transfer(
+ InvokeContext {
+ contract,
+ sender,
+ origin: origin_address,
+ },
+ address,
+ amount,
+ )?;
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::transfer(from, to, amount)?,
+ _ => T::MultiCurrency::transfer(currency_id, from, to, amount)?,
}
+
Self::deposit_event(Event::Transferred(currency_id, from.clone(), to.clone(), amount));
Ok(())
}
@@ -268,14 +302,10 @@ impl MultiCurrency for Pallet {
if amount.is_zero() {
return Ok(());
}
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::deposit(who, amount)?;
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::deposit(currency_id, who, amount)?;
+ match currency_id {
+ CurrencyId::Erc20(_) => return Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::deposit(who, amount)?,
+ _ => T::MultiCurrency::deposit(currency_id, who, amount)?,
}
Self::deposit_event(Event::Deposited(currency_id, who.clone(), amount));
Ok(())
@@ -285,40 +315,28 @@ impl MultiCurrency for Pallet {
if amount.is_zero() {
return Ok(());
}
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::withdraw(who, amount)?;
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::withdraw(currency_id, who, amount)?;
+ match currency_id {
+ CurrencyId::Erc20(_) => return Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::withdraw(who, amount)?,
+ _ => T::MultiCurrency::withdraw(currency_id, who, amount)?,
}
Self::deposit_event(Event::Withdrawn(currency_id, who.clone(), amount));
Ok(())
}
fn can_slash(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> bool {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::can_slash(who, amount)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::can_slash(currency_id, who, amount)
+ match currency_id {
+ CurrencyId::Erc20(_) => false,
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::can_slash(who, amount),
+ _ => T::MultiCurrency::can_slash(currency_id, who, amount),
}
}
fn slash(currency_id: Self::CurrencyId, who: &T::AccountId, amount: Self::Balance) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::slash(who, amount)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::slash(currency_id, who, amount)
+ match currency_id {
+ CurrencyId::Erc20(_) => Default::default(),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::slash(who, amount),
+ _ => T::MultiCurrency::slash(currency_id, who, amount),
}
}
}
@@ -327,14 +345,10 @@ impl MultiCurrencyExtended for Pallet {
type Amount = AmountOf;
fn update_balance(currency_id: Self::CurrencyId, who: &T::AccountId, by_amount: Self::Amount) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::update_balance(who, by_amount)?;
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::update_balance(currency_id, who, by_amount)?;
+ match currency_id {
+ CurrencyId::Erc20(_) => return Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::update_balance(who, by_amount)?,
+ _ => T::MultiCurrency::update_balance(currency_id, who, by_amount)?,
}
Self::deposit_event(Event::BalanceUpdated(currency_id, who.clone(), by_amount));
Ok(())
@@ -350,14 +364,10 @@ impl MultiLockableCurrency for Pallet {
who: &T::AccountId,
amount: Self::Balance,
) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::set_lock(lock_id, who, amount)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::set_lock(lock_id, currency_id, who, amount)
+ match currency_id {
+ CurrencyId::Erc20(_) => Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::set_lock(lock_id, who, amount),
+ _ => T::MultiCurrency::set_lock(lock_id, currency_id, who, amount),
}
}
@@ -367,88 +377,121 @@ impl MultiLockableCurrency for Pallet {
who: &T::AccountId,
amount: Self::Balance,
) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::extend_lock(lock_id, who, amount)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::extend_lock(lock_id, currency_id, who, amount)
+ match currency_id {
+ CurrencyId::Erc20(_) => Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::extend_lock(lock_id, who, amount),
+ _ => T::MultiCurrency::extend_lock(lock_id, currency_id, who, amount),
}
}
fn remove_lock(lock_id: LockIdentifier, currency_id: Self::CurrencyId, who: &T::AccountId) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::remove_lock(lock_id, who)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::remove_lock(lock_id, currency_id, who)
+ match currency_id {
+ CurrencyId::Erc20(_) => Err(Error::::Erc20InvalidOperation.into()),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::remove_lock(lock_id, who),
+ _ => T::MultiCurrency::remove_lock(lock_id, currency_id, who),
}
}
}
impl MultiReservableCurrency for Pallet {
fn can_reserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> bool {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::can_reserve(who, value)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::can_reserve(currency_id, who, value)
+ match currency_id {
+ CurrencyId::Erc20(_) => Self::ensure_can_withdraw(currency_id, who, value).is_ok(),
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::can_reserve(who, value),
+ _ => T::MultiCurrency::can_reserve(currency_id, who, value),
}
}
fn slash_reserved(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::slash_reserved(who, value)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::slash_reserved(currency_id, who, value)
+ match currency_id {
+ CurrencyId::Erc20(_) => value,
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::slash_reserved(who, value),
+ _ => T::MultiCurrency::slash_reserved(currency_id, who, value),
}
}
fn reserved_balance(currency_id: Self::CurrencyId, who: &T::AccountId) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::reserved_balance(who)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::reserved_balance(currency_id, who)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if let Some(address) = T::AddressMapping::get_evm_address(&who) {
+ return T::EVMBridge::balance_of(
+ InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ },
+ reserve_address(address),
+ )
+ .unwrap_or_default();
+ }
+ Default::default()
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::reserved_balance(who),
+ _ => T::MultiCurrency::reserved_balance(currency_id, who),
}
}
+ // TODO: Update to add "claim_cashdrop" using `claim: bool` -
+ // TODO: - Maybe add Claim cashdrop to reserve too, since it -
+ // TODO: - transfers, to "claim_cashdrop" or make it false `claimed: bool = false`.
+ // TODO: - BUT I LEAN TOWARDS THE LATTER.
fn reserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> DispatchResult {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::reserve(who, value)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::reserve(currency_id, who, value)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if value.is_zero() {
+ return Ok(());
+ }
+ let address = T::AddressMapping::get_evm_address(&who).ok_or(Error::::EvmAccountNotFound)?;
+ T::EVMBridge::transfer(
+ InvokeContext {
+ contract,
+ sender: address,
+ origin: address,
+ },
+ reserve_address(address),
+ value,
+ )
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::reserve(who, value),
+ _ => T::MultiCurrency::reserve(currency_id, who, value),
}
}
fn unreserve(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::unreserve(who, value)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::unreserve(currency_id, who, value)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if value.is_zero() {
+ return value;
+ }
+ if let Some(address) = T::AddressMapping::get_evm_address(&who) {
+ let sender = reserve_address(address);
+ let reserved_balance = T::EVMBridge::balance_of(
+ InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ },
+ sender,
+ )
+ .unwrap_or_default();
+ let actual = reserved_balance.min(value);
+ return match T::EVMBridge::transfer(
+ InvokeContext {
+ contract,
+ sender,
+ origin: address,
+ },
+ address,
+ actual,
+ ) {
+ Ok(_) => value - actual,
+ Err(_) => value,
+ };
+ }
+ value
+ }
+ id if id == T::GetNativeCurrencyId::get() => T::NativeCurrency::unreserve(who, value),
+ _ => T::MultiCurrency::unreserve(currency_id, who, value),
}
}
@@ -459,14 +502,63 @@ impl MultiReservableCurrency for Pallet {
value: Self::Balance,
status: BalanceStatus,
) -> result::Result {
- if currency_id == T::GetNativeCurrencyId::get() {
- T::NativeCurrency::repatriate_reserved(slashed, beneficiary, value, status)
- } else {
- ensure!(
- !T::FiatCurrencyIds::get().contains(¤cy_id),
- Error::::InvalidCurrencyType,
- );
- T::MultiCurrency::repatriate_reserved(currency_id, slashed, beneficiary, value, status)
+ match currency_id {
+ CurrencyId::Erc20(contract) => {
+ if value.is_zero() {
+ return Ok(value);
+ }
+ if slashed == beneficiary {
+ return match status {
+ BalanceStatus::Free => Ok(Self::unreserve(currency_id, slashed, value)),
+ BalanceStatus::Reserved => {
+ Ok(value.saturating_sub(Self::reserved_balance(currency_id, slashed)))
+ }
+ };
+ }
+
+ let slashed_address =
+ T::AddressMapping::get_evm_address(&slashed).ok_or(Error::::EvmAccountNotFound)?;
+ let beneficiary_address = T::AddressMapping::get_or_create_evm_address(&beneficiary);
+
+ let slashed_reserve_address = reserve_address(slashed_address);
+ let beneficiary_reserve_address = reserve_address(beneficiary_address);
+
+ let slashed_reserved_balance = T::EVMBridge::balance_of(
+ InvokeContext {
+ contract,
+ sender: Default::default(),
+ origin: Default::default(),
+ },
+ slashed_reserve_address,
+ )
+ .unwrap_or_default();
+ let actual = slashed_reserved_balance.min(value);
+ match status {
+ BalanceStatus::Free => T::EVMBridge::transfer(
+ InvokeContext {
+ contract,
+ sender: slashed_reserve_address,
+ origin: slashed_address,
+ },
+ beneficiary_address,
+ actual,
+ ),
+ BalanceStatus::Reserved => T::EVMBridge::transfer(
+ InvokeContext {
+ contract,
+ sender: slashed_reserve_address,
+ origin: slashed_address,
+ },
+ beneficiary_reserve_address,
+ actual,
+ ),
+ }
+ .map(|_| value - actual)
+ }
+ id if id == T::GetNativeCurrencyId::get() => {
+ T::NativeCurrency::repatriate_reserved(slashed, beneficiary, value, status)
+ }
+ _ => T::MultiCurrency::repatriate_reserved(currency_id, slashed, beneficiary, value, status),
}
}
}
@@ -500,6 +592,7 @@ where
>::ensure_can_withdraw(GetCurrencyId::get(), who, amount)
}
+ // TODO: Update to add "claim_cashdrop" using `claim: bool` -
fn transfer(from: &T::AccountId, to: &T::AccountId, amount: Self::Balance) -> DispatchResult {
as MultiCurrency>::transfer(GetCurrencyId::get(), from, to, amount)
}
@@ -632,6 +725,7 @@ where
Currency::ensure_can_withdraw(who, amount, WithdrawReasons::all(), new_balance)
}
+ // TODO: Update to add "claim_cashdrop" using `claim: bool` -
fn transfer(from: &AccountId, to: &AccountId, amount: Self::Balance) -> DispatchResult {
Currency::transfer(from, to, amount, ExistenceRequirement::AllowDeath)
}
@@ -749,6 +843,7 @@ where
}
}
+ // TODO: Update to add "claim_cashdrop" using `claim: bool` -
impl TransferAll for Pallet {
#[transactional]
fn transfer_all(source: &T::AccountId, dest: &T::AccountId) -> DispatchResult {
@@ -759,3 +854,8 @@ impl TransferAll for Pallet {
T::NativeCurrency::transfer(source, dest, T::NativeCurrency::free_balance(source))
}
}
+
+fn reserve_address(address: EvmAddress) -> EvmAddress {
+ let payload = (b"erc20:", address);
+ EvmAddress::from_slice(&payload.using_encoded(blake2_256)[0..20])
+}
diff --git a/lib-serml/currencies/src/mock.rs b/lib-serml/currencies/src/mock.rs
index 3a8b7c609..f965c3c43 100644
--- a/lib-serml/currencies/src/mock.rs
+++ b/lib-serml/currencies/src/mock.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -20,8 +20,7 @@
#![cfg(test)]
-use super::*;
-use frame_support::{parameter_types, PalletId};
+use frame_support::{assert_ok, ord_parameter_types, parameter_types, traits::GenesisBuild, PalletId};
use orml_traits::parameter_type_with_key;
use primitives::{CurrencyId, TokenSymbol};
use sp_core::H256;
@@ -30,6 +29,12 @@ use sp_runtime::{
traits::{AccountIdConversion, IdentityLookup},
AccountId32, Perbill,
};
+use support::{mocks::MockAddressMapping, AddressMapping};
+
+use super::*;
+use frame_system::EnsureSignedBy;
+use sp_core::{bytes::from_hex, H160};
+use sp_std::str::FromStr;
pub use crate as currencies;
@@ -76,17 +81,17 @@ parameter_type_with_key! {
}
parameter_types! {
- pub DustAccount: AccountId = PalletId(*b"orml/dst").into_account();
+ pub DustAccount: AccountId = PalletId(*b"serml/dst").into_account();
pub const MaxLocks: u32 = 100;
}
-impl orml_tokens::Config for Runtime {
+impl tokens::Config for Runtime {
type Event = Event;
type Balance = Balance;
type Amount = i64;
type CurrencyId = CurrencyId;
type ExistentialDeposits = ExistentialDeposits;
- type OnDust = orml_tokens::TransferDust;
+ type OnDust = tokens::TransferDust;
type WeightInfo = ();
type MaxLocks = MaxLocks;
}
@@ -114,38 +119,138 @@ impl pallet_balances::Config for Runtime {
pub type PalletBalances = pallet_balances::Pallet;
+parameter_types! {
+ pub const MinimumPeriod: u64 = 1000;
+}
+impl pallet_timestamp::Config for Runtime {
+ type Moment = u64;
+ type OnTimestampSet = ();
+ type MinimumPeriod = MinimumPeriod;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const NewContractExtraBytes: u32 = 1;
+ pub NetworkContractSource: H160 = alice_evm_addr();
+}
+
+ord_parameter_types! {
+ pub const CouncilAccount: AccountId32 = AccountId32::from([1u8; 32]);
+ pub const TreasuryAccount: AccountId32 = AccountId32::from([2u8; 32]);
+ pub const NetworkContractAccount: AccountId32 = AccountId32::from([0u8; 32]);
+ pub const StorageDepositPerByte: u128 = 10;
+ pub const MaxCodeSize: u32 = 60 * 1024;
+ pub const DeveloperDeposit: u64 = 1000;
+ pub const DeploymentFee: u64 = 200;
+}
+
+impl setheum_evm::Config for Runtime {
+ type AddressMapping = MockAddressMapping;
+ type Currency = PalletBalances;
+ type TransferAll = ();
+ type NewContractExtraBytes = NewContractExtraBytes;
+ type StorageDepositPerByte = StorageDepositPerByte;
+ type MaxCodeSize = MaxCodeSize;
+
+ type Event = Event;
+ type Precompiles = ();
+ type ChainId = ();
+ type GasToWeight = ();
+ type ChargeTransactionPayment = ();
+ type NetworkContractOrigin = EnsureSignedBy;
+ type NetworkContractSource = NetworkContractSource;
+
+ type DeveloperDeposit = DeveloperDeposit;
+ type DeploymentFee = DeploymentFee;
+ type TreasuryAccount = TreasuryAccount;
+ type FreeDeploymentOrigin = EnsureSignedBy;
+
+ type WeightInfo = ();
+}
+
+impl setheum_evm_bridge::Config for Runtime {
+ type EVM = EVM;
+}
+
impl Config for Runtime {
type Event = Event;
type MultiCurrency = Tokens;
type NativeCurrency = AdaptedBasicCurrency;
type GetNativeCurrencyId = GetNativeCurrencyId;
type WeightInfo = ();
+ type AddressMapping = MockAddressMapping;
+ type EVMBridge = EVMBridge;
}
pub type NativeCurrency = Currency;
pub type AdaptedBasicCurrency = BasicCurrencyAdapter;
-type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
-type Block = frame_system::mocking::MockBlock;
+pub type SignedExtra = setheum_evm::SetEvmOrigin;
+
+pub type Block = sp_runtime::generic::Block;
+pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic;
frame_support::construct_runtime!(
pub enum Runtime where
Block = Block,
- NodeBlock = Block,
- UncheckedExtrinsic = UncheckedExtrinsic,
+ NodeBlock = Block,
+ UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Pallet, Call, Config, Storage, Event},
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
- Tokens: orml_tokens::{Pallet, Storage, Event, Config},
+ Tokens: tokens::{Pallet, Storage, Event, Config},
Currencies: currencies::{Pallet, Call, Event},
+ EVM: setheum_evm::{Pallet, Config, Call, Storage, Event},
+ EVMBridge: setheum_evm_bridge::{Pallet},
}
);
-pub const ALICE: AccountId = AccountId32::new([1u8; 32]);
-pub const BOB: AccountId = AccountId32::new([2u8; 32]);
-pub const EVA: AccountId = AccountId32::new([5u8; 32]);
+pub fn alice() -> AccountId {
+ ::AddressMapping::get_account_id(&alice_evm_addr())
+}
+
+pub fn alice_evm_addr() -> EvmAddress {
+ EvmAddress::from_str("1000000000000000000000000000000000000001").unwrap()
+}
+
+pub fn bob() -> AccountId {
+ ::AddressMapping::get_account_id(&bob_evm_addr())
+}
+
+pub fn bob_evm_addr() -> EvmAddress {
+ EvmAddress::from_str("1000000000000000000000000000000000000002").unwrap()
+}
+
+pub fn eva() -> AccountId {
+ ::AddressMapping::get_account_id(&eva_evm_addr())
+}
+
+pub fn eva_evm_addr() -> EvmAddress {
+ EvmAddress::from_str("1000000000000000000000000000000000000005").unwrap()
+}
+
pub const ID_1: LockIdentifier = *b"1 ";
+pub fn erc20_address() -> EvmAddress {
+ EvmAddress::from_str("0000000000000000000000000000000002000000").unwrap()
+}
+
+pub fn deploy_contracts() {
+ let code = from_hex(include!("../../evm-bridge/src/erc20_demo_contract")).unwrap();
+ assert_ok!(EVM::create_network_contract(
+ Origin::signed(NetworkContractAccount::get()),
+ code,
+ 0,
+ 2100_000,
+ 10000
+ ));
+
+ let event = Event::setheum_evm(setheum_evm::Event::Created(erc20_address()));
+ assert_eq!(System::events().iter().last().unwrap().event, event);
+
+ assert_ok!(EVM::deploy_free(Origin::signed(CouncilAccount::get()), erc20_address()));
+}
+
pub struct ExtBuilder {
endowed_accounts: Vec<(AccountId, CurrencyId, Balance)>,
}
@@ -166,10 +271,10 @@ impl ExtBuilder {
pub fn one_hundred_for_alice_n_bob(self) -> Self {
self.balances(vec![
- (ALICE, NATIVE_CURRENCY_ID, 100),
- (BOB, NATIVE_CURRENCY_ID, 100),
- (ALICE, X_TOKEN_ID, 100),
- (BOB, X_TOKEN_ID, 100),
+ (alice(), NATIVE_CURRENCY_ID, 100),
+ (bob(), NATIVE_CURRENCY_ID, 100),
+ (alice(), X_TOKEN_ID, 100),
+ (bob(), X_TOKEN_ID, 100),
])
}
@@ -190,7 +295,7 @@ impl ExtBuilder {
.assimilate_storage(&mut t)
.unwrap();
- orml_tokens::GenesisConfig:: {
+ tokens::GenesisConfig:: {
endowed_accounts: self
.endowed_accounts
.into_iter()
@@ -200,6 +305,12 @@ impl ExtBuilder {
.assimilate_storage(&mut t)
.unwrap();
- t.into()
+ setheum_evm::GenesisConfig::::default()
+ .assimilate_storage(&mut t)
+ .unwrap();
+
+ let mut ext = sp_io::TestExternalities::new(t);
+ ext.execute_with(|| System::set_block_number(1));
+ ext
}
}
diff --git a/lib-serml/currencies/src/tests.rs b/lib-serml/currencies/src/tests.rs
index 0300473c4..3163bfb5b 100644
--- a/lib-serml/currencies/src/tests.rs
+++ b/lib-serml/currencies/src/tests.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -22,8 +22,13 @@
use super::*;
use frame_support::{assert_noop, assert_ok};
-use mock::{Event, *};
+use mock::{
+ alice, bob, deploy_contracts, erc20_address, eva, AccountId, AdaptedBasicCurrency, Currencies, Event, ExtBuilder,
+ NativeCurrency, Origin, PalletBalances, Runtime, System, Tokens, EVM, ID_1, NATIVE_CURRENCY_ID, X_TOKEN_ID,
+};
+use sp_core::H160;
use sp_runtime::traits::BadOrigin;
+use support::EVM as EVMTrait;
#[test]
fn multi_lockable_currency_should_work() {
@@ -31,10 +36,10 @@ fn multi_lockable_currency_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(Currencies::set_lock(ID_1, X_TOKEN_ID, &ALICE, 50));
- assert_eq!(Tokens::locks(&ALICE, X_TOKEN_ID).len(), 1);
- assert_ok!(Currencies::set_lock(ID_1, NATIVE_CURRENCY_ID, &ALICE, 50));
- assert_eq!(PalletBalances::locks(&ALICE).len(), 1);
+ assert_ok!(Currencies::set_lock(ID_1, X_TOKEN_ID, &alice(), 50));
+ assert_eq!(Tokens::locks(&alice(), X_TOKEN_ID).len(), 1);
+ assert_ok!(Currencies::set_lock(ID_1, NATIVE_CURRENCY_ID, &alice(), 50));
+ assert_eq!(PalletBalances::locks(&alice()).len(), 1);
});
}
@@ -46,13 +51,13 @@ fn multi_reservable_currency_should_work() {
.execute_with(|| {
assert_eq!(Currencies::total_issuance(NATIVE_CURRENCY_ID), 200);
assert_eq!(Currencies::total_issuance(X_TOKEN_ID), 200);
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 100);
- assert_eq!(NativeCurrency::free_balance(&ALICE), 100);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 100);
+ assert_eq!(NativeCurrency::free_balance(&alice()), 100);
- assert_ok!(Currencies::reserve(X_TOKEN_ID, &ALICE, 30));
- assert_ok!(Currencies::reserve(NATIVE_CURRENCY_ID, &ALICE, 40));
- assert_eq!(Currencies::reserved_balance(X_TOKEN_ID, &ALICE), 30);
- assert_eq!(Currencies::reserved_balance(NATIVE_CURRENCY_ID, &ALICE), 40);
+ assert_ok!(Currencies::reserve(X_TOKEN_ID, &alice(), 30));
+ assert_ok!(Currencies::reserve(NATIVE_CURRENCY_ID, &alice(), 40));
+ assert_eq!(Currencies::reserved_balance(X_TOKEN_ID, &alice()), 30);
+ assert_eq!(Currencies::reserved_balance(NATIVE_CURRENCY_ID, &alice()), 40);
});
}
@@ -62,10 +67,10 @@ fn native_currency_lockable_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(NativeCurrency::set_lock(ID_1, &ALICE, 10));
- assert_eq!(PalletBalances::locks(&ALICE).len(), 1);
- assert_ok!(NativeCurrency::remove_lock(ID_1, &ALICE));
- assert_eq!(PalletBalances::locks(&ALICE).len(), 0);
+ assert_ok!(NativeCurrency::set_lock(ID_1, &alice(), 10));
+ assert_eq!(PalletBalances::locks(&alice()).len(), 1);
+ assert_ok!(NativeCurrency::remove_lock(ID_1, &alice()));
+ assert_eq!(PalletBalances::locks(&alice()).len(), 0);
});
}
@@ -75,8 +80,8 @@ fn native_currency_reservable_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(NativeCurrency::reserve(&ALICE, 50));
- assert_eq!(NativeCurrency::reserved_balance(&ALICE), 50);
+ assert_ok!(NativeCurrency::reserve(&alice(), 50));
+ assert_eq!(NativeCurrency::reserved_balance(&alice()), 50);
});
}
@@ -86,10 +91,10 @@ fn basic_currency_adapting_pallet_balances_lockable() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::set_lock(ID_1, &ALICE, 10));
- assert_eq!(PalletBalances::locks(&ALICE).len(), 1);
- assert_ok!(AdaptedBasicCurrency::remove_lock(ID_1, &ALICE));
- assert_eq!(PalletBalances::locks(&ALICE).len(), 0);
+ assert_ok!(AdaptedBasicCurrency::set_lock(ID_1, &alice(), 10));
+ assert_eq!(PalletBalances::locks(&alice()).len(), 1);
+ assert_ok!(AdaptedBasicCurrency::remove_lock(ID_1, &alice()));
+ assert_eq!(PalletBalances::locks(&alice()).len(), 0);
});
}
@@ -99,8 +104,8 @@ fn basic_currency_adapting_pallet_balances_reservable() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::reserve(&ALICE, 50));
- assert_eq!(AdaptedBasicCurrency::reserved_balance(&ALICE), 50);
+ assert_ok!(AdaptedBasicCurrency::reserve(&alice(), 50));
+ assert_eq!(AdaptedBasicCurrency::reserved_balance(&alice()), 50);
});
}
@@ -110,9 +115,10 @@ fn multi_currency_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(Currencies::transfer(Some(ALICE).into(), BOB, X_TOKEN_ID, 50));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 50);
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &BOB), 150);
+ >::set_origin(alice());
+ assert_ok!(Currencies::transfer(Some(alice()).into(), bob(), X_TOKEN_ID, 50));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 50);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &bob()), 150);
});
}
@@ -123,9 +129,11 @@ fn multi_currency_extended_should_work() {
.build()
.execute_with(|| {
assert_ok!(>::update_balance(
- X_TOKEN_ID, &ALICE, 50
+ X_TOKEN_ID,
+ &alice(),
+ 50
));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 150);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 150);
});
}
@@ -135,16 +143,16 @@ fn native_currency_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(Currencies::transfer_native_currency(Some(ALICE).into(), BOB, 50));
- assert_eq!(NativeCurrency::free_balance(&ALICE), 50);
- assert_eq!(NativeCurrency::free_balance(&BOB), 150);
+ assert_ok!(Currencies::transfer_native_currency(Some(alice()).into(), bob(), 50));
+ assert_eq!(NativeCurrency::free_balance(&alice()), 50);
+ assert_eq!(NativeCurrency::free_balance(&bob()), 150);
- assert_ok!(NativeCurrency::transfer(&ALICE, &BOB, 10));
- assert_eq!(NativeCurrency::free_balance(&ALICE), 40);
- assert_eq!(NativeCurrency::free_balance(&BOB), 160);
+ assert_ok!(NativeCurrency::transfer(&alice(), &bob(), 10));
+ assert_eq!(NativeCurrency::free_balance(&alice()), 40);
+ assert_eq!(NativeCurrency::free_balance(&bob()), 160);
- assert_eq!(Currencies::slash(NATIVE_CURRENCY_ID, &ALICE, 10), 0);
- assert_eq!(NativeCurrency::free_balance(&ALICE), 30);
+ assert_eq!(Currencies::slash(NATIVE_CURRENCY_ID, &alice(), 10), 0);
+ assert_eq!(NativeCurrency::free_balance(&alice()), 30);
assert_eq!(NativeCurrency::total_issuance(), 190);
});
}
@@ -155,15 +163,15 @@ fn native_currency_extended_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(NativeCurrency::update_balance(&ALICE, 10));
- assert_eq!(NativeCurrency::free_balance(&ALICE), 110);
+ assert_ok!(NativeCurrency::update_balance(&alice(), 10));
+ assert_eq!(NativeCurrency::free_balance(&alice()), 110);
assert_ok!(>::update_balance(
NATIVE_CURRENCY_ID,
- &ALICE,
+ &alice(),
10
));
- assert_eq!(NativeCurrency::free_balance(&ALICE), 120);
+ assert_eq!(NativeCurrency::free_balance(&alice()), 120);
});
}
@@ -173,14 +181,14 @@ fn basic_currency_adapting_pallet_balances_transfer() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::transfer(&ALICE, &BOB, 50));
- assert_eq!(PalletBalances::total_balance(&ALICE), 50);
- assert_eq!(PalletBalances::total_balance(&BOB), 150);
+ assert_ok!(AdaptedBasicCurrency::transfer(&alice(), &bob(), 50));
+ assert_eq!(PalletBalances::total_balance(&alice()), 50);
+ assert_eq!(PalletBalances::total_balance(&bob()), 150);
// creation fee
- assert_ok!(AdaptedBasicCurrency::transfer(&ALICE, &EVA, 10));
- assert_eq!(PalletBalances::total_balance(&ALICE), 40);
- assert_eq!(PalletBalances::total_balance(&EVA), 10);
+ assert_ok!(AdaptedBasicCurrency::transfer(&alice(), &eva(), 10));
+ assert_eq!(PalletBalances::total_balance(&alice()), 40);
+ assert_eq!(PalletBalances::total_balance(&eva()), 10);
});
}
@@ -190,8 +198,8 @@ fn basic_currency_adapting_pallet_balances_deposit() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::deposit(&EVA, 50));
- assert_eq!(PalletBalances::total_balance(&EVA), 50);
+ assert_ok!(AdaptedBasicCurrency::deposit(&eva(), 50));
+ assert_eq!(PalletBalances::total_balance(&eva()), 50);
assert_eq!(PalletBalances::total_issuance(), 250);
});
}
@@ -202,8 +210,8 @@ fn basic_currency_adapting_pallet_balances_withdraw() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::withdraw(&ALICE, 100));
- assert_eq!(PalletBalances::total_balance(&ALICE), 0);
+ assert_ok!(AdaptedBasicCurrency::withdraw(&alice(), 100));
+ assert_eq!(PalletBalances::total_balance(&alice()), 0);
assert_eq!(PalletBalances::total_issuance(), 100);
});
}
@@ -214,8 +222,8 @@ fn basic_currency_adapting_pallet_balances_slash() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_eq!(AdaptedBasicCurrency::slash(&ALICE, 101), 1);
- assert_eq!(PalletBalances::total_balance(&ALICE), 0);
+ assert_eq!(AdaptedBasicCurrency::slash(&alice(), 101), 1);
+ assert_eq!(PalletBalances::total_balance(&alice()), 0);
assert_eq!(PalletBalances::total_issuance(), 100);
});
}
@@ -226,8 +234,8 @@ fn basic_currency_adapting_pallet_balances_update_balance() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- assert_ok!(AdaptedBasicCurrency::update_balance(&ALICE, -10));
- assert_eq!(PalletBalances::total_balance(&ALICE), 90);
+ assert_ok!(AdaptedBasicCurrency::update_balance(&alice(), -10));
+ assert_eq!(PalletBalances::total_balance(&alice()), 90);
assert_eq!(PalletBalances::total_issuance(), 190);
});
}
@@ -240,14 +248,14 @@ fn update_balance_call_should_work() {
.execute_with(|| {
assert_ok!(Currencies::update_balance(
Origin::root(),
- ALICE,
+ alice(),
NATIVE_CURRENCY_ID,
-10
));
- assert_eq!(NativeCurrency::free_balance(&ALICE), 90);
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 100);
- assert_ok!(Currencies::update_balance(Origin::root(), ALICE, X_TOKEN_ID, 10));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 110);
+ assert_eq!(NativeCurrency::free_balance(&alice()), 90);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 100);
+ assert_ok!(Currencies::update_balance(Origin::root(), alice(), X_TOKEN_ID, 10));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 110);
});
}
@@ -255,7 +263,7 @@ fn update_balance_call_should_work() {
fn update_balance_call_fails_if_not_root_origin() {
ExtBuilder::default().build().execute_with(|| {
assert_noop!(
- Currencies::update_balance(Some(ALICE).into(), ALICE, X_TOKEN_ID, 100),
+ Currencies::update_balance(Some(alice()).into(), alice(), X_TOKEN_ID, 100),
BadOrigin
);
});
@@ -267,30 +275,541 @@ fn call_event_should_work() {
.one_hundred_for_alice_n_bob()
.build()
.execute_with(|| {
- System::set_block_number(1);
-
- assert_ok!(Currencies::transfer(Some(ALICE).into(), BOB, X_TOKEN_ID, 50));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 50);
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &BOB), 150);
- System::assert_last_event(Event::currencies(crate::Event::Transferred(X_TOKEN_ID, ALICE, BOB, 50)));
+ assert_ok!(Currencies::transfer(Some(alice()).into(), bob(), X_TOKEN_ID, 50));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 50);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &bob()), 150);
+ System::assert_last_event(Event::currencies(crate::Event::Transferred(
+ X_TOKEN_ID,
+ alice(),
+ bob(),
+ 50,
+ )));
assert_ok!(>::transfer(
- X_TOKEN_ID, &ALICE, &BOB, 10
+ X_TOKEN_ID,
+ &alice(),
+ &bob(),
+ 10
));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 40);
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &BOB), 160);
- System::assert_last_event(Event::currencies(crate::Event::Transferred(X_TOKEN_ID, ALICE, BOB, 10)));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 40);
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &bob()), 160);
+ System::assert_last_event(Event::currencies(crate::Event::Transferred(
+ X_TOKEN_ID,
+ alice(),
+ bob(),
+ 10,
+ )));
assert_ok!(>::deposit(
- X_TOKEN_ID, &ALICE, 100
+ X_TOKEN_ID,
+ &alice(),
+ 100
));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 140);
- System::assert_last_event(Event::currencies(crate::Event::Deposited(X_TOKEN_ID, ALICE, 100)));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 140);
+ System::assert_last_event(Event::currencies(crate::Event::Deposited(X_TOKEN_ID, alice(), 100)));
assert_ok!(>::withdraw(
- X_TOKEN_ID, &ALICE, 20
+ X_TOKEN_ID,
+ &alice(),
+ 20
+ ));
+ assert_eq!(Currencies::free_balance(X_TOKEN_ID, &alice()), 120);
+ System::assert_last_event(Event::currencies(crate::Event::Withdrawn(X_TOKEN_ID, alice(), 20)));
+ });
+}
+
+#[test]
+fn erc20_total_issuance_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_eq!(Currencies::total_issuance(CurrencyId::Erc20(erc20_address())), 10000);
+ });
+}
+
+#[test]
+fn erc20_free_balance_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ // empty address
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(H160::default()), &alice()),
+ 0
+ );
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 0);
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 10000
+ );
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 0);
+ });
+}
+
+#[test]
+fn erc20_total_balance_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ // empty address
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(H160::default()), &alice()),
+ 0
+ );
+ assert_eq!(Currencies::total_balance(CurrencyId::Erc20(H160::default()), &bob()), 0);
+
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 10000
+ );
+ assert_eq!(Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &bob()), 0);
+ });
+}
+
+#[test]
+fn erc20_ensure_withdraw_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ >::set_origin(alice());
+ assert_ok!(Currencies::ensure_can_withdraw(
+ CurrencyId::Erc20(erc20_address()),
+ &alice(),
+ 100
+ ));
+ assert_eq!(
+ Currencies::ensure_can_withdraw(CurrencyId::Erc20(erc20_address()), &bob(), 100),
+ Err(Error::::BalanceTooLow.into()),
+ );
+ assert_ok!(Currencies::transfer(
+ Origin::signed(alice()),
+ bob(),
+ CurrencyId::Erc20(erc20_address()),
+ 100
+ ));
+ assert_ok!(Currencies::ensure_can_withdraw(
+ CurrencyId::Erc20(erc20_address()),
+ &bob(),
+ 100
+ ));
+ assert_eq!(
+ Currencies::ensure_can_withdraw(CurrencyId::Erc20(erc20_address()), &bob(), 101),
+ Err(Error::::BalanceTooLow.into()),
+ );
+ });
+}
+
+#[test]
+fn erc20_transfer_should_work() {
+ ExtBuilder::default()
+ .balances(vec![
+ (alice(), NATIVE_CURRENCY_ID, 100000),
+ (bob(), NATIVE_CURRENCY_ID, 100000),
+ ])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ let alice_balance = 10000;
+ >::set_origin(alice());
+ >::set_origin(bob());
+ assert_ok!(Currencies::transfer(
+ Origin::signed(alice()),
+ bob(),
+ CurrencyId::Erc20(erc20_address()),
+ 100
+ ));
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 100
+ );
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 100
+ );
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 100
+ );
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 100
+ );
+
+ assert_ok!(Currencies::transfer(
+ Origin::signed(bob()),
+ alice(),
+ CurrencyId::Erc20(erc20_address()),
+ 10
));
- assert_eq!(Currencies::free_balance(X_TOKEN_ID, &ALICE), 120);
- System::assert_last_event(Event::currencies(crate::Event::Withdrawn(X_TOKEN_ID, ALICE, 20)));
+
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 90);
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 90
+ );
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 90
+ );
+ assert_eq!(
+ Currencies::total_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 90
+ );
+ });
+}
+
+#[test]
+fn erc20_transfer_should_fail() {
+ ExtBuilder::default()
+ .balances(vec![
+ (alice(), NATIVE_CURRENCY_ID, 100000),
+ (bob(), NATIVE_CURRENCY_ID, 100000),
+ ])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ >::set_origin(alice());
+ >::set_origin(bob());
+ // empty address
+ assert!(
+ Currencies::transfer(Origin::signed(alice()), bob(), CurrencyId::Erc20(H160::default()), 100).is_err()
+ );
+
+ // bob can't transfer. bob balance 0
+ assert!(
+ Currencies::transfer(Origin::signed(bob()), alice(), CurrencyId::Erc20(erc20_address()), 1).is_err()
+ );
+ });
+}
+
+#[test]
+fn erc20_can_reserve_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_eq!(
+ Currencies::can_reserve(CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ true
+ );
+ });
+}
+
+#[test]
+fn erc20_slash_reserve_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_eq!(
+ Currencies::slash_reserved(CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ 1
+ );
+ assert_ok!(Currencies::reserve(CurrencyId::Erc20(erc20_address()), &alice(), 100));
+ assert_eq!(
+ Currencies::slash_reserved(CurrencyId::Erc20(erc20_address()), &alice(), 10),
+ 10
+ );
+ });
+}
+
+#[test]
+fn erc20_reserve_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ let alice_balance = 10000;
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 0
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+
+ assert_ok!(Currencies::reserve(CurrencyId::Erc20(erc20_address()), &alice(), 100));
+
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 100
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 100
+ );
+ });
+}
+
+#[test]
+fn erc20_unreserve_should_work() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ let alice_balance = 10000;
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 0
+ );
+ assert_eq!(
+ Currencies::unreserve(CurrencyId::Erc20(erc20_address()), &alice(), 0),
+ 0
+ );
+ assert_eq!(
+ Currencies::unreserve(CurrencyId::Erc20(erc20_address()), &alice(), 50),
+ 50
+ );
+ assert_ok!(Currencies::reserve(CurrencyId::Erc20(erc20_address()), &alice(), 30));
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 30
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 30
+ );
+ assert_eq!(
+ Currencies::unreserve(CurrencyId::Erc20(erc20_address()), &alice(), 15),
+ 0
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance - 15
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 15
+ );
+ assert_eq!(
+ Currencies::unreserve(CurrencyId::Erc20(erc20_address()), &alice(), 30),
+ 15
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 0
+ );
+ });
+}
+
+#[test]
+fn erc20_should_not_slash() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_eq!(
+ Currencies::can_slash(CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ false
+ );
+ // calling slash will return 0
+ assert_eq!(Currencies::slash(CurrencyId::Erc20(erc20_address()), &alice(), 1), 0);
+ });
+}
+
+#[test]
+fn erc20_should_not_be_lockable() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_noop!(
+ Currencies::set_lock(ID_1, CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ Error::::Erc20InvalidOperation
+ );
+ assert_noop!(
+ Currencies::extend_lock(ID_1, CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ Error::::Erc20InvalidOperation
+ );
+ assert_noop!(
+ Currencies::remove_lock(ID_1, CurrencyId::Erc20(erc20_address()), &alice()),
+ Error::::Erc20InvalidOperation
+ );
+ });
+}
+
+#[test]
+fn erc20_repatriate_reserved_should_work() {
+ ExtBuilder::default()
+ .balances(vec![
+ (alice(), NATIVE_CURRENCY_ID, 100000),
+ (bob(), NATIVE_CURRENCY_ID, 100000),
+ ])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ let bob_balance = 100;
+ let alice_balance = 10000 - bob_balance;
+ >::set_origin(alice());
+ assert_ok!(Currencies::transfer(
+ Origin::signed(alice()),
+ bob(),
+ CurrencyId::Erc20(erc20_address()),
+ bob_balance
+ ));
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 0
+ );
+ assert_eq!(
+ Currencies::repatriate_reserved(
+ CurrencyId::Erc20(erc20_address()),
+ &alice(),
+ &alice(),
+ 0,
+ BalanceStatus::Free
+ ),
+ Ok(0)
+ );
+ assert_eq!(
+ Currencies::repatriate_reserved(
+ CurrencyId::Erc20(erc20_address()),
+ &alice(),
+ &alice(),
+ 50,
+ BalanceStatus::Free
+ ),
+ Ok(50)
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 0
+ );
+
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ bob_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 0
+ );
+ assert_ok!(Currencies::reserve(CurrencyId::Erc20(erc20_address()), &bob(), 50));
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 50);
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 50
+ );
+ assert_eq!(
+ Currencies::repatriate_reserved(
+ CurrencyId::Erc20(erc20_address()),
+ &bob(),
+ &bob(),
+ 60,
+ BalanceStatus::Reserved
+ ),
+ Ok(10)
+ );
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 50);
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 50
+ );
+
+ assert_eq!(
+ Currencies::repatriate_reserved(
+ CurrencyId::Erc20(erc20_address()),
+ &bob(),
+ &alice(),
+ 30,
+ BalanceStatus::Reserved
+ ),
+ Ok(0)
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 30
+ );
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 50);
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 20
+ );
+
+ assert_eq!(
+ Currencies::repatriate_reserved(
+ CurrencyId::Erc20(erc20_address()),
+ &bob(),
+ &alice(),
+ 30,
+ BalanceStatus::Free
+ ),
+ Ok(10)
+ );
+ assert_eq!(
+ Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ alice_balance + 20
+ );
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &alice()),
+ 30
+ );
+ assert_eq!(Currencies::free_balance(CurrencyId::Erc20(erc20_address()), &bob()), 50);
+ assert_eq!(
+ Currencies::reserved_balance(CurrencyId::Erc20(erc20_address()), &bob()),
+ 0
+ );
+ });
+}
+
+#[test]
+fn erc20_invalid_operation() {
+ ExtBuilder::default()
+ .balances(vec![(alice(), NATIVE_CURRENCY_ID, 100000)])
+ .build()
+ .execute_with(|| {
+ deploy_contracts();
+ assert_noop!(
+ Currencies::deposit(CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ Error::::Erc20InvalidOperation
+ );
+ assert_noop!(
+ Currencies::withdraw(CurrencyId::Erc20(erc20_address()), &alice(), 1),
+ Error::::Erc20InvalidOperation
+ );
+ assert_noop!(
+ Currencies::update_balance(Origin::root(), alice(), CurrencyId::Erc20(erc20_address()), 1),
+ Error::::Erc20InvalidOperation,
+ );
});
}
diff --git a/lib-serml/currencies/src/weights.rs b/lib-serml/currencies/src/weights.rs
index 481d8dcfc..b3d01c45a 100644
--- a/lib-serml/currencies/src/weights.rs
+++ b/lib-serml/currencies/src/weights.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -24,19 +24,23 @@
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
// Executed Command:
-// /Users/xiliangchen/projects/acala/target/release/acala
// benchmark
// --chain=dev
// --steps=50
// --repeat=20
-// --pallet=module_currencies
+// --pallet=setheum_currencies
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --output=./currencies/src/weights.rs
-// --template
-// ../templates/orml-weight-template.hbs
+// --template=./templates/module-weight-template.hbs
+
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
#![cfg_attr(rustfmt, rustfmt_skip)]
@@ -47,7 +51,7 @@
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;
-/// Weight functions needed for module_currencies.
+/// Weight functions needed for setheum_currencies.
pub trait WeightInfo {
fn transfer_non_native_currency() -> Weight;
fn transfer_native_currency() -> Weight;
@@ -56,31 +60,49 @@ pub trait WeightInfo {
fn update_balance_native_currency_killing() -> Weight;
}
-/// Default weights.
+/// Weights for setheum_currencies using the Setheum node and recommended hardware.
+pub struct SetheumWeight(PhantomData);
+impl WeightInfo for SetheumWeight {
+ fn transfer_non_native_currency() -> Weight {
+ (65_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(6 as Weight))
+ .saturating_add(T::DbWeight::get().writes(6 as Weight))
+ }
+ fn transfer_native_currency() -> Weight {
+ (11_000_000 as Weight)
+ }
+ fn update_balance_non_native_currency() -> Weight {
+ (31_000_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(3 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
+ }
+ fn update_balance_native_currency_creating() -> Weight {
+ (14_000_000 as Weight)
+ }
+ fn update_balance_native_currency_killing() -> Weight {
+ (13_000_000 as Weight)
+ }
+}
+
+// For backwards compatibility and tests
impl WeightInfo for () {
fn transfer_non_native_currency() -> Weight {
- (60_000_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(5 as Weight))
- .saturating_add(RocksDbWeight::get().writes(4 as Weight))
+ (65_000_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(6 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
fn transfer_native_currency() -> Weight {
- (60_000_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(3 as Weight))
- .saturating_add(RocksDbWeight::get().writes(2 as Weight))
+ (11_000_000 as Weight)
}
fn update_balance_non_native_currency() -> Weight {
- (29_000_000 as Weight)
+ (31_000_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
fn update_balance_native_currency_creating() -> Weight {
- (31_000_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(1 as Weight))
- .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ (14_000_000 as Weight)
}
fn update_balance_native_currency_killing() -> Weight {
- (37_000_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(3 as Weight))
- .saturating_add(RocksDbWeight::get().writes(2 as Weight))
+ (13_000_000 as Weight)
}
}
diff --git a/lib-serml/dex/src/lib.rs b/lib-serml/dex/src/lib.rs
index ec89eb096..f64c249c1 100644
--- a/lib-serml/dex/src/lib.rs
+++ b/lib-serml/dex/src/lib.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -34,13 +34,13 @@ use frame_support::{log, pallet_prelude::*, traits::MaxEncodedLen, transactional
use frame_system::pallet_prelude::*;
use orml_traits::{MultiCurrency, MultiCurrencyExtended};
use primitives::{Balance, CurrencyId, TradingPair};
-use sp_core::U256;
+use sp_core::{H160, U256};
use sp_runtime::{
traits::{AccountIdConversion, UniqueSaturatedInto, Zero},
DispatchError, DispatchResult, FixedPointNumber, RuntimeDebug, SaturatedConversion,
};
use sp_std::{convert::TryInto, prelude::*, vec};
-use support::{DexIncentives, DexManager, Price, Ratio};
+use support::{CurrencyIdMapping, DEXIncentives, DEXManager, Price, Ratio};
mod mock;
mod tests;
@@ -105,15 +105,19 @@ pub mod module {
#[pallet::constant]
type TradingPathLimit: Get;
- /// The Dex's module id, keep all assets in Dex.
+ /// The DEX's module id, keep all assets in DEX.
#[pallet::constant]
type PalletId: Get;
+ /// Mapping between CurrencyId and ERC20 address so user can use Erc20
+ /// address as LP token.
+ type CurrencyIdMapping: CurrencyIdMapping;
+
/// Weight information for the extrinsics in this module.
type WeightInfo: WeightInfo;
/// Dex incentives
- type DexIncentives: DexIncentives;
+ type DEXIncentives: DEXIncentives;
/// The origin which may list, enable or disable trading pairs.
type ListingOrigin: EnsureOrigin;
@@ -185,17 +189,24 @@ pub mod module {
}
/// Liquidity pool for TradingPair.
+ ///
+ /// LiquidityPool: map TradingPair => (Balance, Balance)
#[pallet::storage]
#[pallet::getter(fn liquidity_pool)]
pub type LiquidityPool = StorageMap<_, Twox64Concat, TradingPair, (Balance, Balance), ValueQuery>;
/// Status for TradingPair.
+ ///
+ /// TradingPairStatuses: map TradingPair => TradingPairStatus
#[pallet::storage]
#[pallet::getter(fn trading_pair_statuses)]
pub type TradingPairStatuses =
StorageMap<_, Twox64Concat, TradingPair, TradingPairStatus, ValueQuery>;
/// Provision of TradingPair by AccountId.
+ ///
+ /// ProvisioningPool: double_map TradingPair, AccountId => (Balance,
+ /// Balance)
#[pallet::storage]
#[pallet::getter(fn provisioning_pool)]
pub type ProvisioningPool =
@@ -286,7 +297,7 @@ pub mod module {
#[pallet::call]
impl Pallet {
- /// Trading with Dex, swap with exact supply amount
+ /// Trading with DEX, swap with exact supply amount
///
/// - `path`: trading path.
/// - `supply_amount`: exact supply amount.
@@ -304,7 +315,7 @@ pub mod module {
Ok(().into())
}
- /// Trading with Dex, swap with exact target amount
+ /// Trading with DEX, swap with exact target amount
///
/// - `path`: trading path.
/// - `target_amount`: exact target amount.
@@ -446,6 +457,13 @@ pub mod module {
Error::::NotAllowedList
);
+ if let CurrencyId::Erc20(address) = currency_id_a {
+ T::CurrencyIdMapping::set_erc20_mapping(address)?;
+ }
+ if let CurrencyId::Erc20(address) = currency_id_b {
+ T::CurrencyIdMapping::set_erc20_mapping(address)?;
+ }
+
let (min_contribution, target_provision) = if currency_id_a == trading_pair.0 {
(
(min_contribution_a, min_contribution_b),
@@ -780,7 +798,7 @@ impl Pallet {
*pool_1 = pool_1.saturating_add(pool_1_increment);
if deposit_increment_share {
- T::DexIncentives::do_deposit_dex_share(who, lp_share_currency_id, share_increment)?;
+ T::DEXIncentives::do_deposit_dex_share(who, lp_share_currency_id, share_increment)?;
}
Self::deposit_event(Event::AddLiquidity(
@@ -832,7 +850,7 @@ impl Pallet {
);
if by_withdraw {
- T::DexIncentives::do_withdraw_dex_share(who, lp_share_currency_id, remove_share)?;
+ T::DEXIncentives::do_withdraw_dex_share(who, lp_share_currency_id, remove_share)?;
}
T::Currency::withdraw(lp_share_currency_id, &who, remove_share)?;
T::Currency::transfer(trading_pair.0, &module_account_id, &who, pool_0_decrement)?;
@@ -905,6 +923,7 @@ impl Pallet {
}
}
+ // TODO: Set Custom Governed FlexibleTradingFees for each path
fn get_target_amounts(
path: &[CurrencyId],
supply_amount: Balance,
@@ -1084,11 +1103,17 @@ impl Pallet {
}
}
-impl DexManager for Pallet {
+impl DEXManager for Pallet {
fn get_liquidity_pool(currency_id_a: CurrencyId, currency_id_b: CurrencyId) -> (Balance, Balance) {
Self::get_liquidity(currency_id_a, currency_id_b)
}
+ fn get_liquidity_token_address(currency_id_a: CurrencyId, currency_id_b: CurrencyId) -> Option {
+ let trading_pair = TradingPair::from_token_currency_ids(currency_id_a, currency_id_b)?;
+ let dex_share_currency_id = trading_pair.get_dex_share_currency_id()?;
+ T::CurrencyIdMapping::encode_evm_address(dex_share_currency_id)
+ }
+
fn get_swap_target_amount(
path: &[CurrencyId],
supply_amount: Balance,
diff --git a/lib-serml/dex/src/mock.rs b/lib-serml/dex/src/mock.rs
index a9bd36906..e5649e37e 100644
--- a/lib-serml/dex/src/mock.rs
+++ b/lib-serml/dex/src/mock.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -34,11 +34,12 @@ pub type AccountId = u128;
pub const ALICE: AccountId = 1;
pub const BOB: AccountId = 2;
pub const USDJ: CurrencyId = CurrencyId::Token(TokenSymbol::USDJ);
-pub const JCHF: CurrencyId = CurrencyId::Token(TokenSymbol::JCHF);
+pub const EURJ: CurrencyId = CurrencyId::Token(TokenSymbol::EURJ);
+pub const CHFJ: CurrencyId = CurrencyId::Token(TokenSymbol::CHFJ);
pub const DNAR: CurrencyId = CurrencyId::Token(TokenSymbol::DNAR);
-pub const USDJ_JCHF_PAIR: TradingPair = TradingPair(USDJ, JCHF);
+pub const USDJ_CHFJ_PAIR: TradingPair = TradingPair(USDJ, CHFJ);
pub const USDJ_DNAR_PAIR: TradingPair = TradingPair(USDJ, DNAR);
-pub const DNAR_JCHF_PAIR: TradingPair = TradingPair(DNAR, JCHF);
+pub const DNAR_CHFJ_PAIR: TradingPair = TradingPair(DNAR, CHFJ);
mod dex {
pub use super::super::*;
@@ -91,8 +92,8 @@ impl orml_tokens::Config for Runtime {
type MaxLocks = ();
}
-pub struct MockDexIncentives;
-impl DexIncentives for MockDexIncentives {
+pub struct MockDEXIncentives;
+impl DEXIncentives for MockDEXIncentives {
fn do_deposit_dex_share(who: &AccountId, lp_currency_id: CurrencyId, amount: Balance) -> DispatchResult {
Tokens::reserve(lp_currency_id, who, amount)
}
@@ -110,7 +111,7 @@ ord_parameter_types! {
parameter_types! {
pub const GetExchangeFee: (u32, u32) = (1, 100);
pub const TradingPathLimit: u32 = 3;
- pub const DexPalletId: PalletId = PalletId(*b"dnr/sdex");
+ pub const DexPalletId: PalletId = PalletId(*b"set/sdex");
}
impl Config for Runtime {
@@ -118,9 +119,10 @@ impl Config for Runtime {
type Currency = Tokens;
type GetExchangeFee = GetExchangeFee;
type TradingPathLimit = TradingPathLimit;
- type PalletId = DexPalletId;
+ type PalletId = DEXPalletId;
+ type CurrencyIdMapping = ();
type WeightInfo = ();
- type DexIncentives = MockDexIncentives;
+ type DEXIncentives = MockDEXIncentives;
type ListingOrigin = EnsureSignedBy;
}
@@ -134,7 +136,7 @@ construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Storage, Config, Event},
- Dex: dex::{Pallet, Storage, Call, Event, Config},
+ SetheumDEX: dex::{Pallet, Storage, Call, Event, Config},
Tokens: orml_tokens::{Pallet, Storage, Event, Config},
}
);
@@ -152,8 +154,10 @@ impl Default for ExtBuilder {
endowed_accounts: vec![
(ALICE, USDJ, 1_000_000_000_000_000_000u128),
(BOB, USDJ, 1_000_000_000_000_000_000u128),
- (ALICE, JCHF, 1_000_000_000_000_000_000u128),
- (BOB, JCHF, 1_000_000_000_000_000_000u128),
+ (ALICE, EURJ, 1_000_000_000_000_000_000u128),
+ (BOB, EURJ, 1_000_000_000_000_000_000u128),
+ (ALICE, CHFJ, 1_000_000_000_000_000_000u128),
+ (BOB, CHFJ, 1_000_000_000_000_000_000u128),
(ALICE, DNAR, 1_000_000_000_000_000_000u128),
(BOB, DNAR, 1_000_000_000_000_000_000u128),
],
@@ -174,13 +178,13 @@ impl ExtBuilder {
10,
),
(
- USDJ_JCHF_PAIR,
+ USDJ_CHFJ_PAIR,
(20_000_000_000_000u128, 1_000_000_000u128),
(20_000_000_000_000_000u128, 1_000_000_000_000u128),
10,
),
(
- DNAR_JCHF_PAIR,
+ DNAR_CHFJ_PAIR,
(4_000_000_000_000u128, 1_000_000_000u128),
(4_000_000_000_000_000u128, 1_000_000_000_000u128),
20,
@@ -190,7 +194,7 @@ impl ExtBuilder {
}
pub fn initialize_enabled_trading_pairs(mut self) -> Self {
- self.initial_enabled_trading_pairs = vec![USDJ_DNAR_PAIR, USDJ_JCHF_PAIR, DNAR_JCHF_PAIR];
+ self.initial_enabled_trading_pairs = vec![USDJ_DNAR_PAIR, USDJ_CHFJ_PAIR, DNAR_CHFJ_PAIR];
self
}
@@ -199,8 +203,8 @@ impl ExtBuilder {
who,
vec![
(USDJ_DNAR_PAIR, (1_000_000u128, 2_000_000u128)),
- (USDJ_JCHF_PAIR, (1_000_000u128, 2_000_000u128)),
- (DNAR_JCHF_PAIR, (1_000_000u128, 2_000_000u128)),
+ (USDJ_CHFJ_PAIR, (1_000_000u128, 2_000_000u128)),
+ (DNAR_CHFJ_PAIR, (1_000_000u128, 2_000_000u128)),
],
)];
self
diff --git a/lib-serml/dex/src/tests.rs b/lib-serml/dex/src/tests.rs
index 3dc0631e6..290b29884 100644
--- a/lib-serml/dex/src/tests.rs
+++ b/lib-serml/dex/src/tests.rs
@@ -1,6 +1,6 @@
// This file is part of Setheum.
-// Copyright (C) 2020-2021 Setheum Labs.
+// Copyright (C) 2019-2021 Setheum Labs.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
use super::*;
use frame_support::{assert_noop, assert_ok};
use mock::{
- Dex, Event, ExtBuilder, ListingOrigin, Origin, Runtime, System, Tokens, DNAR, ALICE, USDJ, USDJ_DNAR_PAIR,
- USDJ_JCHF_PAIR, BOB, JCHF,
+ SetheumDEX, Event, ExtBuilder, ListingOrigin, Origin, Runtime, System, Tokens,
+ ALICE, BOB, DNAR, USDJ, EURJ, CHFJ, USDJ_DNAR_PAIR, USDJ_CHFJ_PAIR,
};
use orml_traits::MultiReservableCurrency;
use sp_runtime::traits::BadOrigin;
@@ -35,28 +35,27 @@ fn enable_new_trading_pair_work() {
System::set_block_number(1);
assert_noop!(
- Dex::enable_trading_pair(Origin::signed(ALICE), USDJ, DNAR),
+ SetheumDEX::enable_trading_pair(Origin::signed(ALICE), USDJ, DNAR),
BadOrigin
);
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::NotEnabled
);
- assert_ok!(Dex::enable_trading_pair(
+ assert_ok!(SetheumDEX::enable_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Enabled
);
-
System::assert_last_event(Event::dex(crate::Event::EnableTradingPair(USDJ_DNAR_PAIR)));
assert_noop!(
- Dex::enable_trading_pair(Origin::signed(ListingOrigin::get()), DNAR, USDJ),
+ SetheumDEX::enable_trading_pair(Origin::signed(ListingOrigin::get()), DNAR, USDJ),
Error::::MustBeNotEnabled
);
});
@@ -68,7 +67,7 @@ fn list_new_trading_pair_work() {
System::set_block_number(1);
assert_noop!(
- Dex::list_trading_pair(
+ SetheumDEX::list_trading_pair(
Origin::signed(ALICE),
USDJ,
DNAR,
@@ -82,10 +81,10 @@ fn list_new_trading_pair_work() {
);
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::NotEnabled
);
- assert_ok!(Dex::list_trading_pair(
+ assert_ok!(SetheumDEX::list_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR,
@@ -96,7 +95,7 @@ fn list_new_trading_pair_work() {
10,
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Provisioning(TradingPairProvisionParameters {
min_contribution: (1_000_000_000_000u128, 1_000_000_000_000u128),
target_provision: (5_000_000_000_000u128, 2_000_000_000_000u128),
@@ -104,13 +103,13 @@ fn list_new_trading_pair_work() {
not_before: 10,
})
);
-
System::assert_last_event(Event::dex(crate::Event::ListTradingPair(USDJ_DNAR_PAIR)));
+
assert_noop!(
- Dex::list_trading_pair(
+ SetheumDEX::list_trading_pair(
Origin::signed(ListingOrigin::get()),
- DNAR,
- DNAR,
+ USDJ,
+ USDJ,
1_000_000_000_000u128,
1_000_000_000_000u128,
5_000_000_000_000u128,
@@ -121,7 +120,7 @@ fn list_new_trading_pair_work() {
);
assert_noop!(
- Dex::list_trading_pair(
+ SetheumDEX::list_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR,
@@ -141,34 +140,34 @@ fn disable_enabled_trading_pair_work() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
- assert_ok!(Dex::enable_trading_pair(
+ assert_ok!(SetheumDEX::enable_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Enabled
);
assert_noop!(
- Dex::disable_trading_pair(Origin::signed(ALICE), USDJ, DNAR),
+ SetheumDEX::disable_trading_pair(Origin::signed(ALICE), USDJ, DNAR),
BadOrigin
);
- assert_ok!(Dex::disable_trading_pair(
+ assert_ok!(SetheumDEX::disable_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::NotEnabled
);
-
System::assert_last_event(Event::dex(crate::Event::DisableTradingPair(USDJ_DNAR_PAIR)));
+
assert_noop!(
- Dex::disable_trading_pair(Origin::signed(ListingOrigin::get()), USDJ, DNAR),
+ SetheumDEX::disable_trading_pair(Origin::signed(ListingOrigin::get()), USDJ, DNAR),
Error::::NotEnabledTradingPair
);
});
@@ -182,20 +181,22 @@ fn disable_provisioning_trading_pair_work() {
.execute_with(|| {
System::set_block_number(1);
- assert_ok!(Dex::add_liquidity(
+ assert_ok!(SetheumDEX::add_liquidity(
Origin::signed(ALICE),
USDJ,
DNAR,
5_000_000_000_000u128,
0,
+ 0,
false
));
- assert_ok!(Dex::add_liquidity(
+ assert_ok!(SetheumDEX::add_liquidity(
Origin::signed(BOB),
USDJ,
DNAR,
5_000_000_000_000u128,
1_000_000_000_000u128,
+ 0,
false
));
@@ -204,23 +205,23 @@ fn disable_provisioning_trading_pair_work() {
assert_eq!(Tokens::free_balance(USDJ, &BOB), 999_995_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &BOB), 999_999_000_000_000_000u128);
assert_eq!(
- Tokens::free_balance(USDJ, &Dex::account_id()),
+ Tokens::free_balance(USDJ, &SetheumDEX::account_id()),
10_000_000_000_000u128
);
assert_eq!(
- Tokens::free_balance(DNAR, &Dex::account_id()),
+ Tokens::free_balance(DNAR, &SetheumDEX::account_id()),
1_000_000_000_000u128
);
assert_eq!(
- Dex::provisioning_pool(USDJ_DNAR_PAIR, ALICE),
+ SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, ALICE),
(5_000_000_000_000u128, 0)
);
assert_eq!(
- Dex::provisioning_pool(USDJ_DNAR_PAIR, BOB),
+ SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, BOB),
(5_000_000_000_000u128, 1_000_000_000_000u128)
);
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Provisioning(TradingPairProvisionParameters {
min_contribution: (5_000_000_000_000u128, 1_000_000_000_000u128),
target_provision: (5_000_000_000_000_000u128, 1_000_000_000_000_000u128),
@@ -231,7 +232,7 @@ fn disable_provisioning_trading_pair_work() {
let alice_ref_count_0 = System::consumers(&ALICE);
let bob_ref_count_0 = System::consumers(&BOB);
- assert_ok!(Dex::disable_trading_pair(
+ assert_ok!(SetheumDEX::disable_trading_pair(
Origin::signed(ListingOrigin::get()),
USDJ,
DNAR
@@ -240,12 +241,12 @@ fn disable_provisioning_trading_pair_work() {
assert_eq!(Tokens::free_balance(DNAR, &ALICE), 1_000_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(USDJ, &BOB), 1_000_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &BOB), 1_000_000_000_000_000_000u128);
- assert_eq!(Tokens::free_balance(USDJ, &Dex::account_id()), 0);
- assert_eq!(Tokens::free_balance(DNAR, &Dex::account_id()), 0);
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
+ assert_eq!(Tokens::free_balance(USDJ, &SetheumDEX::account_id()), 0);
+ assert_eq!(Tokens::free_balance(DNAR, &SetheumDEX::account_id()), 0);
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::NotEnabled
);
assert_eq!(System::consumers(&ALICE), alice_ref_count_0 - 1);
@@ -262,12 +263,13 @@ fn add_provision_work() {
System::set_block_number(1);
assert_noop!(
- Dex::add_liquidity(
+ SetheumDEX::add_liquidity(
Origin::signed(ALICE),
USDJ,
DNAR,
4_999_999_999_999u128,
999_999_999_999u128,
+ 0,
false
),
Error::::InvalidContributionIncrement
@@ -275,7 +277,7 @@ fn add_provision_work() {
// alice add provision
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Provisioning(TradingPairProvisionParameters {
min_contribution: (5_000_000_000_000u128, 1_000_000_000_000u128),
target_provision: (5_000_000_000_000_000u128, 1_000_000_000_000_000u128),
@@ -283,23 +285,24 @@ fn add_provision_work() {
not_before: 10,
})
);
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
assert_eq!(Tokens::free_balance(USDJ, &ALICE), 1_000_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &ALICE), 1_000_000_000_000_000_000u128);
- assert_eq!(Tokens::free_balance(USDJ, &Dex::account_id()), 0);
- assert_eq!(Tokens::free_balance(DNAR, &Dex::account_id()), 0);
+ assert_eq!(Tokens::free_balance(USDJ, &SetheumDEX::account_id()), 0);
+ assert_eq!(Tokens::free_balance(DNAR, &SetheumDEX::account_id()), 0);
let alice_ref_count_0 = System::consumers(&ALICE);
- assert_ok!(Dex::add_liquidity(
+ assert_ok!(SetheumDEX::add_liquidity(
Origin::signed(ALICE),
USDJ,
DNAR,
5_000_000_000_000u128,
0,
+ 0,
false
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Provisioning(TradingPairProvisionParameters {
min_contribution: (5_000_000_000_000u128, 1_000_000_000_000u128),
target_provision: (5_000_000_000_000_000u128, 1_000_000_000_000_000u128),
@@ -308,16 +311,16 @@ fn add_provision_work() {
})
);
assert_eq!(
- Dex::provisioning_pool(USDJ_DNAR_PAIR, ALICE),
+ SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, ALICE),
(5_000_000_000_000u128, 0)
);
assert_eq!(Tokens::free_balance(USDJ, &ALICE), 999_995_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &ALICE), 1_000_000_000_000_000_000u128);
assert_eq!(
- Tokens::free_balance(USDJ, &Dex::account_id()),
+ Tokens::free_balance(USDJ, &SetheumDEX::account_id()),
5_000_000_000_000u128
);
- assert_eq!(Tokens::free_balance(DNAR, &Dex::account_id()), 0);
+ assert_eq!(Tokens::free_balance(DNAR, &SetheumDEX::account_id()), 0);
let alice_ref_count_1 = System::consumers(&ALICE);
assert_eq!(alice_ref_count_1, alice_ref_count_0 + 1);
System::assert_last_event(Event::dex(crate::Event::AddProvision(
@@ -329,21 +332,22 @@ fn add_provision_work() {
)));
// bob add provision
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
assert_eq!(Tokens::free_balance(USDJ, &BOB), 1_000_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &BOB), 1_000_000_000_000_000_000u128);
let bob_ref_count_0 = System::consumers(&BOB);
- assert_ok!(Dex::add_liquidity(
+ assert_ok!(SetheumDEX::add_liquidity(
Origin::signed(BOB),
DNAR,
USDJ,
1_000_000_000_000_000u128,
0,
+ 0,
false
));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Provisioning(TradingPairProvisionParameters {
min_contribution: (5_000_000_000_000u128, 1_000_000_000_000u128),
target_provision: (5_000_000_000_000_000u128, 1_000_000_000_000_000u128),
@@ -352,17 +356,17 @@ fn add_provision_work() {
})
);
assert_eq!(
- Dex::provisioning_pool(USDJ_DNAR_PAIR, BOB),
+ SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, BOB),
(0, 1_000_000_000_000_000u128)
);
assert_eq!(Tokens::free_balance(USDJ, &BOB), 1_000_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &BOB), 999_000_000_000_000_000u128);
assert_eq!(
- Tokens::free_balance(USDJ, &Dex::account_id()),
+ Tokens::free_balance(USDJ, &SetheumDEX::account_id()),
5_000_000_000_000u128
);
assert_eq!(
- Tokens::free_balance(DNAR, &Dex::account_id()),
+ Tokens::free_balance(DNAR, &SetheumDEX::account_id()),
1_000_000_000_000_000u128
);
let bob_ref_count_1 = System::consumers(&BOB);
@@ -393,22 +397,23 @@ fn add_provision_work() {
);
System::set_block_number(10);
- assert_ok!(Dex::add_liquidity(
+ assert_ok!(SetheumDEX::add_liquidity(
Origin::signed(ALICE),
USDJ,
DNAR,
995_000_000_000_000u128,
1_000_000_000_000_000u128,
+ 0,
false
));
assert_eq!(Tokens::free_balance(USDJ, &ALICE), 999_000_000_000_000_000u128);
assert_eq!(Tokens::free_balance(DNAR, &ALICE), 999_000_000_000_000_000u128);
assert_eq!(
- Tokens::free_balance(USDJ, &Dex::account_id()),
+ Tokens::free_balance(USDJ, &SetheumDEX::account_id()),
1_000_000_000_000_000u128
);
assert_eq!(
- Tokens::free_balance(DNAR, &Dex::account_id()),
+ Tokens::free_balance(DNAR, &SetheumDEX::account_id()),
2_000_000_000_000_000u128
);
assert_eq!(
@@ -423,13 +428,12 @@ fn add_provision_work() {
Tokens::free_balance(USDJ_DNAR_PAIR.get_dex_share_currency_id().unwrap(), &BOB),
1_000_000_000_000_000,
);
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
- assert_eq!(Dex::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, ALICE), (0, 0));
+ assert_eq!(SetheumDEX::provisioning_pool(USDJ_DNAR_PAIR, BOB), (0, 0));
assert_eq!(
- Dex::trading_pair_statuses(USDJ_DNAR_PAIR),
+ SetheumDEX::trading_pair_statuses(USDJ_DNAR_PAIR),
TradingPairStatus::<_, _>::Enabled
);
-
System::assert_last_event(Event::dex(crate::Event::ProvisioningToEnabled(
USDJ_DNAR_PAIR,
1_000_000_000_000_000u128,
@@ -443,35 +447,35 @@ fn add_provision_work() {
fn get_liquidity_work() {
ExtBuilder::default().build().execute_with(|| {
LiquidityPool::::insert(USDJ_DNAR_PAIR, (1000, 20));
- assert_eq!(Dex::liquidity_pool(USDJ_DNAR_PAIR), (1000, 20));
- assert_eq!(Dex::get_liquidity(USDJ, DNAR), (1000, 20));
- assert_eq!(Dex::get_liquidity(DNAR, USDJ), (20, 1000));
+ assert_eq!(SetheumDEX::liquidity_pool(USDJ_DNAR_PAIR), (1000, 20));
+ assert_eq!(SetheumDEX::get_liquidity(USDJ, DNAR), (1000, 20));
+ assert_eq!(SetheumDEX::get_liquidity(DNAR, USDJ), (20, 1000));
});
}
#[test]
fn get_target_amount_work() {
ExtBuilder::default().build().execute_with(|| {
- assert_eq!(Dex::get_target_amount(10000, 0, 1000), 0);
- assert_eq!(Dex::get_target_amount(0, 20000, 1000), 0);
- assert_eq!(Dex::get_target_amount(10000, 20000, 0), 0);
- assert_eq!(Dex::get_target_amount(10000, 1, 1000000), 0);
- assert_eq!(Dex::get_target_amount(10000, 20000, 10000), 9949);
- assert_eq!(Dex::get_target_amount(10000, 20000, 1000), 1801);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 0, 1000), 0);
+ assert_eq!(SetheumDEX::get_target_amount(0, 20000, 1000), 0);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 20000, 0), 0);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 1, 1000000), 0);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 20000, 10000), 9949);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 20000, 1000), 1801);
});
}
#[test]
fn get_supply_amount_work() {
ExtBuilder::default().build().execute_with(|| {
- assert_eq!(Dex::get_supply_amount(10000, 0, 1000), 0);
- assert_eq!(Dex::get_supply_amount(0, 20000, 1000), 0);
- assert_eq!(Dex::get_supply_amount(10000, 20000, 0), 0);
- assert_eq!(Dex::get_supply_amount(10000, 1, 1), 0);
- assert_eq!(Dex::get_supply_amount(10000, 20000, 9949), 9999);
- assert_eq!(Dex::get_target_amount(10000, 20000, 9999), 9949);
- assert_eq!(Dex::get_supply_amount(10000, 20000, 1801), 1000);
- assert_eq!(Dex::get_target_amount(10000, 20000, 1000), 1801);
+ assert_eq!(SetheumDEX::get_supply_amount(10000, 0, 1000), 0);
+ assert_eq!(SetheumDEX::get_supply_amount(0, 20000, 1000), 0);
+ assert_eq!(SetheumDEX::get_supply_amount(10000, 20000, 0), 0);
+ assert_eq!(SetheumDEX::get_supply_amount(10000, 1, 1), 0);
+ assert_eq!(SetheumDEX::get_supply_amount(10000, 20000, 9949), 9999);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 20000, 9999), 9949);
+ assert_eq!(SetheumDEX::get_supply_amount(10000, 20000, 1801), 1000);
+ assert_eq!(SetheumDEX::get_target_amount(10000, 20000, 1000), 1801);
});
}
@@ -482,41 +486,37 @@ fn get_target_amounts_work() {
.build()
.execute_with(|| {
LiquidityPool::::insert(USDJ_DNAR_PAIR, (50000, 10000));
- LiquidityPool::::insert(USDJ_JCHF_PAIR, (100000, 10));
+ LiquidityPool::::insert(USDJ_CHFJ_PAIR, (100000, 10));
assert_noop!(
- Dex::get_target_amounts(&vec![DNAR], 10000, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR], 10000, None),
Error::::InvalidTradingPathLength,
);
assert_noop!(
- Dex::get_target_amounts(&vec![DNAR, USDJ, JCHF], 10000, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ, CHFJ, EURJ], 10000, None),
Error::::InvalidTradingPathLength,
);
- assert_noop!(
- Dex::get_target_amounts(&vec![DNAR, USDJ], 10000, None),
- Error::::MustBeEnabled,
- );
assert_eq!(
- Dex::get_target_amounts(&vec![DNAR, USDJ], 10000, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ], 10000, None),
Ok(vec![10000, 24874])
);
assert_eq!(
- Dex::get_target_amounts(&vec![DNAR, USDJ], 10000, Ratio::checked_from_rational(50, 100)),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ], 10000, Ratio::checked_from_rational(50, 100)),
Ok(vec![10000, 24874])
);
assert_noop!(
- Dex::get_target_amounts(&vec![DNAR, USDJ], 10000, Ratio::checked_from_rational(49, 100)),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ], 10000, Ratio::checked_from_rational(49, 100)),
Error::::ExceedPriceImpactLimit,
);
assert_eq!(
- Dex::get_target_amounts(&vec![DNAR, USDJ, JCHF], 10000, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ, CHFJ], 10000, None),
Ok(vec![10000, 24874, 1])
);
assert_noop!(
- Dex::get_target_amounts(&vec![DNAR, USDJ, JCHF], 100, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR, USDJ, CHFJ], 100, None),
Error::::ZeroTargetAmount,
);
assert_noop!(
- Dex::get_target_amounts(&vec![DNAR, JCHF], 100, None),
+ SetheumDEX::get_target_amounts(&vec![DNAR, CHFJ], 100, None),
Error::::InsufficientLiquidity,
);
});
@@ -530,7 +530,7 @@ fn calculate_amount_for_big_number_work() {
(171_000_000_000_000_000_000_000, 56_000_000_000_000_000_000_000),
);
assert_eq!(
- Dex::get_supply_amount(
+ SetheumDEX::get_supply_amount(
171_000_000_000_000_000_000_000,
56_000_000_000_000_000_000_000,
1_000_000_000_000_000_000_000
@@ -538,7 +538,7 @@ fn calculate_amount_for_big_number_work() {
3_140_495_867_768_595_041_323
);
assert_eq!(
- Dex::get_target_amount(
+ SetheumDEX::get_target_amount(
171_000_000_000_000_000_000_000,
56_000_000_000_000_000_000_000,
3_140_495_867_768_595_041_323
@@ -555,37 +555,33 @@ fn get_supply_amounts_work() {
.build()
.execute_with(|| {
LiquidityPool::