--- /dev/null
+++ b/.maintain/scripts/generate_abi.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -eu
+
+dir=$PWD
+
+tmp=$(mktemp -d)
+cd $tmp
+cp $dir/$INPUT input.sol
+solcjs --abi -p input.sol
+
+NAME=input_sol_$(basename $INPUT .sol)
+mv $NAME.abi $NAME.json
+prettier $NAME.json > $dir/$OUTPUT
--- a/.maintain/scripts/generate_api.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-set -eu
-
-tmp=$(mktemp)
-cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp
-raw=$(mktemp --suffix .sol)
-sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
-formatted=$(mktemp)
-prettier --use-tabs $raw > $formatted
-
-mv $formatted $OUTPUT
--- /dev/null
+++ b/.maintain/scripts/generate_sol.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -eu
+
+tmp=$(mktemp)
+cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp
+raw=$(mktemp --suffix .sol)
+sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
+formatted=$(mktemp)
+prettier --use-tabs $raw > $formatted
+
+mv $formatted $OUTPUT
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4290,6 +4290,9 @@
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin",
+]
[[package]]
name = "lazycell"
@@ -5467,9 +5470,9 @@
[[package]]
name = "once_cell"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca"
+checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "opal-runtime"
@@ -5917,6 +5920,7 @@
"frame-benchmarking",
"frame-support",
"frame-system",
+ "lazy_static",
"pallet-evm",
"pallet-evm-coder-substrate",
"parity-scale-codec 3.1.2",
@@ -6083,6 +6087,7 @@
"frame-support",
"frame-system",
"log",
+ "pallet-common",
"pallet-evm",
"pallet-evm-coder-substrate",
"parity-scale-codec 3.1.2",
@@ -6090,6 +6095,7 @@
"sp-core",
"sp-runtime",
"sp-std",
+ "up-data-structs",
"up-sponsorship",
]
@@ -6814,13 +6820,18 @@
name = "pallet-unique"
version = "0.1.0"
dependencies = [
+ "ethereum",
+ "evm-coder",
"frame-benchmarking",
"frame-support",
"frame-system",
"pallet-common",
"pallet-evm",
+ "pallet-evm-coder-substrate",
+ "pallet-nonfungible",
"parity-scale-codec 3.1.2",
"scale-info",
+ "serde",
"sp-core",
"sp-io",
"sp-runtime",
@@ -12005,9 +12016,9 @@
[[package]]
name = "target-lexicon"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1"
+checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
[[package]]
name = "tempfile"
--- a/Makefile
+++ b/Makefile
@@ -1,33 +1,61 @@
.PHONY: _help
_help:
@echo "regenerate_solidity - generate stubs/interfaces for contracts defined in native (via evm-coder)"
- @echo "evm_stubs - recompile contract stubs"
+ @echo "evm_stubs - recompile contract stubs and ABI"
@echo "bench - run frame-benchmarking"
@echo " bench-evm-migration"
@echo " bench-unique"
+FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs
+FUNGIBLE_EVM_ABI=./tests/src/eth/fungibleAbi.json
+
+NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs
+NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json
+
+CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/
+CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json
+
+COLLECTION_HELPER_STUBS=./pallets/unique/src/eth/stubs/
+COLLECTION_HELPER_ABI=./tests/src/eth/collectionHelperAbi.json
+
+TESTS_API=./tests/src/eth/api/
+
.PHONY: regenerate_solidity
-regenerate_solidity:
- PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=./tests/src/eth/api/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
- PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=./tests/src/eth/api/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
- PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=./tests/src/eth/api/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelper.sol
+
+UniqueFungible.sol:
+ PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
+ PACKAGE=pallet-fungible NAME=erc::gen_impl OUTPUT=$(FUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
+
+UniqueNFT.sol:
+ PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
+ PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
+
+ContractHelpers.sol:
+ PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
+ PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
+
+CollectionHelper.sol:
+ PACKAGE=pallet-unique NAME=eth::collection_helper_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
+ PACKAGE=pallet-unique NAME=eth::collection_helper_impl OUTPUT=$(COLLECTION_HELPER_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
+
+UniqueFungible: UniqueFungible.sol
+ INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw ./.maintain/scripts/compile_stub.sh
+ INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh
- PACKAGE=pallet-fungible NAME=erc::gen_impl OUTPUT=./pallets/fungible/src/stubs/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
- PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=./pallets/nonfungible/src/stubs/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
- PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=./pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+UniqueNFT: UniqueNFT.sol
+ INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw ./.maintain/scripts/compile_stub.sh
+ INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh
-FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs
-NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs
-CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/
+ContractHelpers: ContractHelpers.sol
+ INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh
+ INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_ABI) ./.maintain/scripts/generate_abi.sh
-$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw: $(FUNGIBLE_EVM_STUBS)/UniqueFungible.sol
- INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
-$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw: $(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.sol
- INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
-$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw: $(CONTRACT_HELPERS_STUBS)/ContractHelpers.sol
- INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+CollectionHelper: CollectionHelper.sol
+ INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelper.raw ./.maintain/scripts/compile_stub.sh
+ INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh
-evm_stubs: $(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw $(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw $(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw
+evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelper
.PHONY: _bench
_bench:
--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -327,7 +327,7 @@
}
}
-#[impl_for_tuples(1, 5)]
+#[impl_for_tuples(1, 12)]
impl SolidityArguments for Tuple {
for_tuples!( where #( Tuple: SolidityArguments ),* );
--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -16,16 +16,18 @@
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" }
+frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" }
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" }
+
serde = { version = "1.0.130", default-features = false }
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
-frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" }
+lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] }
[features]
default = ["std"]
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -14,12 +14,17 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see .
-use evm_coder::{solidity_interface, types::*, execution::Result};
+use evm_coder::{
+ solidity_interface,
+ types::*,
+ execution::{Result, Error},
+};
pub use pallet_evm::{PrecompileOutput, PrecompileResult, account::CrossAccountId};
use pallet_evm_coder_substrate::dispatch_to_evm;
use sp_core::{H160, U256};
use sp_std::vec::Vec;
-use up_data_structs::Property;
+use up_data_structs::{Property, SponsoringRateLimit};
+use alloc::format;
use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
@@ -31,7 +36,7 @@
fn call(self, source: &H160, input: &[u8], value: U256) -> Option;
}
-#[solidity_interface(name = "CollectionProperties")]
+#[solidity_interface(name = "Collection")]
impl CollectionHandle {
fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -64,4 +69,93 @@
Ok(prop.to_vec())
}
+
+ fn eth_set_sponsor(&mut self, caller: caller, sponsor: address) -> Result {
+ check_is_owner(caller, self)?;
+
+ let sponsor = T::CrossAccountId::from_eth(sponsor);
+ self.set_sponsor(sponsor.as_sub().clone());
+ save(self);
+ Ok(())
+ }
+
+ fn eth_confirm_sponsorship(&mut self, caller: caller) -> Result {
+ let caller = T::CrossAccountId::from_eth(caller);
+ if !self.confirm_sponsorship(caller.as_sub()) {
+ return Err(Error::Revert("Caller is not set as sponsor".into()));
+ }
+ save(self);
+ Ok(())
+ }
+
+ fn set_limit(&mut self, caller: caller, limit: string, value: string) -> Result {
+ check_is_owner(caller, self)?;
+ let mut limits = self.limits.clone();
+
+ match limit.as_str() {
+ "accountTokenOwnershipLimit" => {
+ limits.account_token_ownership_limit = parse_int(value)?;
+ }
+ "sponsoredDataSize" => {
+ limits.sponsored_data_size = parse_int(value)?;
+ }
+ "sponsoredDataRateLimit" => {
+ limits.sponsored_data_rate_limit =
+ Some(SponsoringRateLimit::Blocks(parse_int(value)?.unwrap()));
+ }
+ "tokenLimit" => {
+ limits.token_limit = parse_int(value)?;
+ }
+ "sponsorTransferTimeout" => {
+ limits.sponsor_transfer_timeout = parse_int(value)?;
+ }
+ "sponsorApproveTimeout" => {
+ limits.sponsor_approve_timeout = parse_int(value)?;
+ }
+ "ownerCanTransfer" => {
+ limits.owner_can_transfer = parse_bool(value)?;
+ }
+ "ownerCanDestroy" => {
+ limits.owner_can_destroy = parse_bool(value)?;
+ }
+ "transfersEnabled" => {
+ limits.transfers_enabled = parse_bool(value)?;
+ }
+ _ => return Err(Error::Revert(format!("Unknown limit \"{}\"", limit))),
+ }
+ self.limits = >::clamp_limits(self.mode.clone(), &self.limits, limits)
+ .map_err(dispatch_to_evm::)?;
+ save(self);
+ Ok(())
+ }
+
+ fn contract_address(&self, _caller: caller) -> Result {
+ Ok(crate::eth::collection_id_to_address(self.id))
+ }
+}
+
+fn check_is_owner(caller: caller, collection: &CollectionHandle) -> Result<()> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ collection
+ .check_is_owner(&caller)
+ .map_err(pallet_evm_coder_substrate::dispatch_to_evm::)?;
+ Ok(())
+}
+
+fn save(collection: &CollectionHandle) {
+ >::insert(collection.id, collection.collection.clone());
+}
+
+fn parse_int(value: string) -> Result