difftreelog
Merge branch 'develop' into tests/eth-helpers
in: master
21 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -37,6 +37,7 @@
Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
eth::{
EthCrossAccount, convert_cross_account_to_uint256, CollectionPermissions as EvmPermissions,
+ CollectionLimits as EvmCollectionLimits,
},
weights::WeightInfo,
};
@@ -304,6 +305,99 @@
Ok(result)
}
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ fn collection_limits(&self) -> Result<Vec<(EvmCollectionLimits, bool, uint256)>> {
+ let convert_value_limit = |limit: EvmCollectionLimits,
+ value: Option<u32>|
+ -> (EvmCollectionLimits, bool, uint256) {
+ value
+ .map(|v| (limit, true, v.into()))
+ .unwrap_or((limit, false, Default::default()))
+ };
+
+ let convert_bool_limit = |limit: EvmCollectionLimits,
+ value: Option<bool>|
+ -> (EvmCollectionLimits, bool, uint256) {
+ value
+ .map(|v| {
+ (
+ limit,
+ true,
+ if v {
+ uint256::from(1)
+ } else {
+ Default::default()
+ },
+ )
+ })
+ .unwrap_or((limit, false, Default::default()))
+ };
+
+ let limits = &self.collection.limits;
+
+ Ok(vec![
+ convert_value_limit(
+ EvmCollectionLimits::AccountTokenOwnership,
+ limits.account_token_ownership_limit,
+ ),
+ convert_value_limit(
+ EvmCollectionLimits::SponsoredDataSize,
+ limits.sponsored_data_size,
+ ),
+ limits
+ .sponsored_data_rate_limit
+ .and_then(|limit| {
+ if let SponsoringRateLimit::Blocks(blocks) = limit {
+ Some((
+ EvmCollectionLimits::SponsoredDataRateLimit,
+ true,
+ blocks.into(),
+ ))
+ } else {
+ None
+ }
+ })
+ .unwrap_or((
+ EvmCollectionLimits::SponsoredDataRateLimit,
+ false,
+ Default::default(),
+ )),
+ convert_value_limit(EvmCollectionLimits::TokenLimit, limits.token_limit),
+ convert_value_limit(
+ EvmCollectionLimits::SponsorTransferTimeout,
+ limits.sponsor_transfer_timeout,
+ ),
+ convert_value_limit(
+ EvmCollectionLimits::SponsorApproveTimeout,
+ limits.sponsor_approve_timeout,
+ ),
+ convert_bool_limit(
+ EvmCollectionLimits::OwnerCanTransfer,
+ limits.owner_can_transfer,
+ ),
+ convert_bool_limit(
+ EvmCollectionLimits::OwnerCanDestroy,
+ limits.owner_can_destroy,
+ ),
+ convert_bool_limit(
+ EvmCollectionLimits::TransferEnabled,
+ limits.transfers_enabled,
+ ),
+ ])
+ }
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -316,11 +410,22 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
#[solidity(rename_selector = "setCollectionLimit")]
- fn set_int_limit(&mut self, caller: caller, limit: string, value: uint256) -> Result<void> {
+ fn set_collection_limit(
+ &mut self,
+ caller: caller,
+ limit: EvmCollectionLimits,
+ status: bool,
+ value: uint256,
+ ) -> Result<void> {
self.consume_store_reads_and_writes(1, 1)?;
+ if !status {
+ return Err(Error::Revert("user can't disable limits".into()));
+ }
+
let value = value
.try_into()
.map_err(|_| Error::Revert(format!("can't convert value to u32 \"{}\"", value)))?;
@@ -338,35 +443,35 @@
let mut limits = self.limits.clone();
- match limit.as_str() {
- "accountTokenOwnershipLimit" => {
+ match limit {
+ EvmCollectionLimits::AccountTokenOwnership => {
limits.account_token_ownership_limit = Some(value);
}
- "sponsoredDataSize" => {
+ EvmCollectionLimits::SponsoredDataSize => {
limits.sponsored_data_size = Some(value);
}
- "sponsoredDataRateLimit" => {
+ EvmCollectionLimits::SponsoredDataRateLimit => {
limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(value));
}
- "tokenLimit" => {
+ EvmCollectionLimits::TokenLimit => {
limits.token_limit = Some(value);
}
- "sponsorTransferTimeout" => {
+ EvmCollectionLimits::SponsorTransferTimeout => {
limits.sponsor_transfer_timeout = Some(value);
}
- "sponsorApproveTimeout" => {
+ EvmCollectionLimits::SponsorApproveTimeout => {
limits.sponsor_approve_timeout = Some(value);
}
- "ownerCanTransfer" => {
+ EvmCollectionLimits::OwnerCanTransfer => {
limits.owner_can_transfer = Some(convert_value_to_bool()?);
}
- "ownerCanDestroy" => {
+ EvmCollectionLimits::OwnerCanDestroy => {
limits.owner_can_destroy = Some(convert_value_to_bool()?);
}
- "transfersEnabled" => {
+ EvmCollectionLimits::TransferEnabled => {
limits.transfers_enabled = Some(convert_value_to_bool()?);
}
- _ => return Err(Error::Revert(format!("unknown limit \"{}\"", limit))),
+ _ => return Err(Error::Revert(format!("unknown limit \"{:?}\"", limit))),
}
let caller = T::CrossAccountId::from_eth(caller);
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -155,6 +155,31 @@
}
}
}
+
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+#[derive(Debug, Default, Clone, Copy, AbiCoder)]
+#[repr(u8)]
+pub enum CollectionLimits {
+ /// How many tokens can a user have on one account.
+ #[default]
+ AccountTokenOwnership,
+ /// How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// How many tokens can be mined into this collection.
+ TokenLimit,
+ /// Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// Is it possible to send tokens from this collection between users.
+ TransferEnabled,
+}
#[derive(Default, Debug, Clone, Copy, AbiCoder)]
#[repr(u8)]
pub enum CollectionPermissions {
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -18,7 +18,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -158,6 +158,27 @@
return Tuple8(0x0000000000000000000000000000000000000000, 0);
}
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() public view returns (Tuple20[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple20[](0);
+ }
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -170,12 +191,18 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) public {
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) public {
require(false, stub_error);
limit;
+ status;
value;
dummy = 0;
}
@@ -257,19 +284,19 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() public view returns (Tuple21 memory) {
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple26 memory) {
require(false, stub_error);
dummy;
- return Tuple21(false, new uint256[](0));
+ return Tuple26(false, new uint256[](0));
}
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() public view returns (Tuple24[] memory) {
+ function collectionNestingPermissions() public view returns (Tuple29[] memory) {
require(false, stub_error);
dummy;
- return new Tuple24[](0);
+ return new Tuple29[](0);
}
/// Set the collection access method.
@@ -449,17 +476,46 @@
}
/// @dev anonymous struct
-struct Tuple24 {
+struct Tuple29 {
CollectionPermissions field_0;
bool field_1;
}
/// @dev anonymous struct
-struct Tuple21 {
+struct Tuple26 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple20 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev Property struct
struct Property {
string key;
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -42,18 +42,19 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple48[] memory permissions) public {
+ function setTokenPropertyPermissions(Tuple59[] memory permissions) public {
require(false, stub_error);
permissions;
dummy = 0;
}
+ /// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() public view returns (Tuple48[] memory) {
+ function tokenPropertyPermissions() public view returns (Tuple59[] memory) {
require(false, stub_error);
dummy;
- return new Tuple48[](0);
+ return new Tuple59[](0);
}
// /// @notice Set token property value.
@@ -132,26 +133,30 @@
bytes value;
}
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
+ /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
Mutable,
+ /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
TokenOwner,
+ /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
}
/// @dev anonymous struct
-struct Tuple48 {
+struct Tuple59 {
string field_0;
- Tuple46[] field_1;
+ Tuple57[] field_1;
}
/// @dev anonymous struct
-struct Tuple46 {
+struct Tuple57 {
EthTokenPermissions field_0;
bool field_1;
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -291,6 +296,27 @@
return Tuple30(0x0000000000000000000000000000000000000000, 0);
}
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() public view returns (Tuple33[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple33[](0);
+ }
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -303,12 +329,18 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) public {
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) public {
require(false, stub_error);
limit;
+ status;
value;
dummy = 0;
}
@@ -390,19 +422,19 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() public view returns (Tuple34 memory) {
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple39 memory) {
require(false, stub_error);
dummy;
- return Tuple34(false, new uint256[](0));
+ return Tuple39(false, new uint256[](0));
}
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() public view returns (Tuple37[] memory) {
+ function collectionNestingPermissions() public view returns (Tuple42[] memory) {
require(false, stub_error);
dummy;
- return new Tuple37[](0);
+ return new Tuple42[](0);
}
/// Set the collection access method.
@@ -582,17 +614,46 @@
}
/// @dev anonymous struct
-struct Tuple37 {
+struct Tuple42 {
CollectionPermissions field_0;
bool field_1;
}
/// @dev anonymous struct
-struct Tuple34 {
+struct Tuple39 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple33 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev anonymous struct
struct Tuple30 {
address field_0;
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -42,7 +42,7 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple53[] memory permissions) public {
+ function setTokenPropertyPermissions(Tuple58[] memory permissions) public {
require(false, stub_error);
permissions;
dummy = 0;
@@ -51,10 +51,10 @@
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() public view returns (Tuple53[] memory) {
+ function tokenPropertyPermissions() public view returns (Tuple58[] memory) {
require(false, stub_error);
dummy;
- return new Tuple53[](0);
+ return new Tuple58[](0);
}
// /// @notice Set token property value.
@@ -133,26 +133,30 @@
bytes value;
}
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
+ /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
Mutable,
+ /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
TokenOwner,
+ /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
}
/// @dev anonymous struct
-struct Tuple53 {
+struct Tuple58 {
string field_0;
- Tuple51[] field_1;
+ Tuple56[] field_1;
}
/// @dev anonymous struct
-struct Tuple51 {
+struct Tuple56 {
EthTokenPermissions field_0;
bool field_1;
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
contract Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -292,6 +296,27 @@
return Tuple29(0x0000000000000000000000000000000000000000, 0);
}
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() public view returns (Tuple32[] memory) {
+ require(false, stub_error);
+ dummy;
+ return new Tuple32[](0);
+ }
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -304,12 +329,18 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) public {
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) public {
require(false, stub_error);
limit;
+ status;
value;
dummy = 0;
}
@@ -391,19 +422,19 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() public view returns (Tuple33 memory) {
+ function collectionNestingRestrictedCollectionIds() public view returns (Tuple38 memory) {
require(false, stub_error);
dummy;
- return Tuple33(false, new uint256[](0));
+ return Tuple38(false, new uint256[](0));
}
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() public view returns (Tuple36[] memory) {
+ function collectionNestingPermissions() public view returns (Tuple41[] memory) {
require(false, stub_error);
dummy;
- return new Tuple36[](0);
+ return new Tuple41[](0);
}
/// Set the collection access method.
@@ -583,17 +614,46 @@
}
/// @dev anonymous struct
-struct Tuple36 {
+struct Tuple41 {
CollectionPermissions field_0;
bool field_1;
}
/// @dev anonymous struct
-struct Tuple33 {
+struct Tuple38 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple32 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev anonymous struct
struct Tuple29 {
address field_0;
tests/src/eth/abi/fungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -208,6 +208,28 @@
},
{
"inputs": [],
+ "name": "collectionLimits",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" },
+ { "internalType": "uint256", "name": "field_2", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple20[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingPermissions",
"outputs": [
{
@@ -219,7 +241,7 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple24[]",
+ "internalType": "struct Tuple29[]",
"name": "",
"type": "tuple[]"
}
@@ -240,7 +262,7 @@
"type": "uint256[]"
}
],
- "internalType": "struct Tuple21",
+ "internalType": "struct Tuple26",
"name": "",
"type": "tuple"
}
@@ -453,7 +475,12 @@
},
{
"inputs": [
- { "internalType": "string", "name": "limit", "type": "string" },
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "limit",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "status", "type": "bool" },
{ "internalType": "uint256", "name": "value", "type": "uint256" }
],
"name": "setCollectionLimit",
tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -238,6 +238,28 @@
},
{
"inputs": [],
+ "name": "collectionLimits",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" },
+ { "internalType": "uint256", "name": "field_2", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple33[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingPermissions",
"outputs": [
{
@@ -249,7 +271,7 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple37[]",
+ "internalType": "struct Tuple42[]",
"name": "",
"type": "tuple[]"
}
@@ -270,7 +292,7 @@
"type": "uint256[]"
}
],
- "internalType": "struct Tuple34",
+ "internalType": "struct Tuple39",
"name": "",
"type": "tuple"
}
@@ -607,7 +629,12 @@
},
{
"inputs": [
- { "internalType": "string", "name": "limit", "type": "string" },
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "limit",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "status", "type": "bool" },
{ "internalType": "uint256", "name": "value", "type": "uint256" }
],
"name": "setCollectionLimit",
@@ -709,12 +736,12 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple46[]",
+ "internalType": "struct Tuple57[]",
"name": "field_1",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple48[]",
+ "internalType": "struct Tuple59[]",
"name": "permissions",
"type": "tuple[]"
}
@@ -775,12 +802,12 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple46[]",
+ "internalType": "struct Tuple57[]",
"name": "field_1",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple48[]",
+ "internalType": "struct Tuple59[]",
"name": "",
"type": "tuple[]"
}
tests/src/eth/abi/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -220,6 +220,28 @@
},
{
"inputs": [],
+ "name": "collectionLimits",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "field_0",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "field_1", "type": "bool" },
+ { "internalType": "uint256", "name": "field_2", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple32[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
"name": "collectionNestingPermissions",
"outputs": [
{
@@ -231,7 +253,7 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple36[]",
+ "internalType": "struct Tuple41[]",
"name": "",
"type": "tuple[]"
}
@@ -252,7 +274,7 @@
"type": "uint256[]"
}
],
- "internalType": "struct Tuple33",
+ "internalType": "struct Tuple38",
"name": "",
"type": "tuple"
}
@@ -589,7 +611,12 @@
},
{
"inputs": [
- { "internalType": "string", "name": "limit", "type": "string" },
+ {
+ "internalType": "enum CollectionLimits",
+ "name": "limit",
+ "type": "uint8"
+ },
+ { "internalType": "bool", "name": "status", "type": "bool" },
{ "internalType": "uint256", "name": "value", "type": "uint256" }
],
"name": "setCollectionLimit",
@@ -691,12 +718,12 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple51[]",
+ "internalType": "struct Tuple56[]",
"name": "field_1",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple53[]",
+ "internalType": "struct Tuple58[]",
"name": "permissions",
"type": "tuple[]"
}
@@ -766,12 +793,12 @@
},
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
- "internalType": "struct Tuple51[]",
+ "internalType": "struct Tuple56[]",
"name": "field_1",
"type": "tuple[]"
}
],
- "internalType": "struct Tuple53[]",
+ "internalType": "struct Tuple58[]",
"name": "",
"type": "tuple[]"
}
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -104,6 +104,23 @@
/// or in textual repr: collectionSponsor()
function collectionSponsor() external view returns (Tuple8 memory);
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() external view returns (Tuple19[] memory);
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -116,10 +133,15 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) external;
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) external;
/// Get contract address.
/// @dev EVM selector for this function is: 0xf6b4dfb4,
@@ -169,12 +191,12 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() external view returns (Tuple20 memory);
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple24 memory);
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() external view returns (Tuple23[] memory);
+ function collectionNestingPermissions() external view returns (Tuple27[] memory);
/// Set the collection access method.
/// @param mode Access mode
@@ -289,7 +311,7 @@
}
/// @dev anonymous struct
-struct Tuple23 {
+struct Tuple27 {
CollectionPermissions field_0;
bool field_1;
}
@@ -300,11 +322,40 @@
}
/// @dev anonymous struct
-struct Tuple20 {
+struct Tuple24 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple19 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev Property struct
struct Property {
string key;
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -30,11 +30,12 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple43[] memory permissions) external;
+ function setTokenPropertyPermissions(Tuple52[] memory permissions) external;
+ /// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() external view returns (Tuple43[] memory);
+ function tokenPropertyPermissions() external view returns (Tuple52[] memory);
// /// @notice Set token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -85,26 +86,30 @@
bytes value;
}
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
+ /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
Mutable,
+ /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
TokenOwner,
+ /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
}
/// @dev anonymous struct
-struct Tuple43 {
+struct Tuple52 {
string field_0;
- Tuple41[] field_1;
+ Tuple50[] field_1;
}
/// @dev anonymous struct
-struct Tuple41 {
+struct Tuple50 {
EthTokenPermissions field_0;
bool field_1;
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -195,6 +200,23 @@
/// or in textual repr: collectionSponsor()
function collectionSponsor() external view returns (Tuple27 memory);
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() external view returns (Tuple30[] memory);
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -207,10 +229,15 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) external;
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) external;
/// Get contract address.
/// @dev EVM selector for this function is: 0xf6b4dfb4,
@@ -260,12 +287,12 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() external view returns (Tuple31 memory);
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple35 memory);
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() external view returns (Tuple34[] memory);
+ function collectionNestingPermissions() external view returns (Tuple38[] memory);
/// Set the collection access method.
/// @param mode Access mode
@@ -380,7 +407,7 @@
}
/// @dev anonymous struct
-struct Tuple34 {
+struct Tuple38 {
CollectionPermissions field_0;
bool field_1;
}
@@ -391,11 +418,40 @@
}
/// @dev anonymous struct
-struct Tuple31 {
+struct Tuple35 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple30 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev anonymous struct
struct Tuple27 {
address field_0;
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -30,12 +30,12 @@
/// @param permissions Permissions for keys.
/// @dev EVM selector for this function is: 0xbd92983a,
/// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
- function setTokenPropertyPermissions(Tuple47[] memory permissions) external;
+ function setTokenPropertyPermissions(Tuple51[] memory permissions) external;
/// @notice Get permissions for token properties.
/// @dev EVM selector for this function is: 0xf23d7790,
/// or in textual repr: tokenPropertyPermissions()
- function tokenPropertyPermissions() external view returns (Tuple47[] memory);
+ function tokenPropertyPermissions() external view returns (Tuple51[] memory);
// /// @notice Set token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -86,26 +86,30 @@
bytes value;
}
+/// @dev Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
enum EthTokenPermissions {
+ /// @dev Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
Mutable,
+ /// @dev Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
TokenOwner,
+ /// @dev Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
CollectionAdmin
}
/// @dev anonymous struct
-struct Tuple47 {
+struct Tuple51 {
string field_0;
- Tuple45[] field_1;
+ Tuple49[] field_1;
}
/// @dev anonymous struct
-struct Tuple45 {
+struct Tuple49 {
EthTokenPermissions field_0;
bool field_1;
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+/// @dev the ERC-165 identifier for this interface is 0x81172a75
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -196,6 +200,23 @@
/// or in textual repr: collectionSponsor()
function collectionSponsor() external view returns (Tuple26 memory);
+ /// Get current collection limits.
+ ///
+ /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:
+ /// "accountTokenOwnershipLimit",
+ /// "sponsoredDataSize",
+ /// "sponsoredDataRateLimit",
+ /// "tokenLimit",
+ /// "sponsorTransferTimeout",
+ /// "sponsorApproveTimeout"
+ /// "ownerCanTransfer",
+ /// "ownerCanDestroy",
+ /// "transfersEnabled"
+ /// Return `false` if a limit not set.
+ /// @dev EVM selector for this function is: 0xf63bc572,
+ /// or in textual repr: collectionLimits()
+ function collectionLimits() external view returns (Tuple29[] memory);
+
/// Set limits for the collection.
/// @dev Throws error if limit not found.
/// @param limit Name of the limit. Valid names:
@@ -208,10 +229,15 @@
/// "ownerCanTransfer",
/// "ownerCanDestroy",
/// "transfersEnabled"
+ /// @param status enable\disable limit. Works only with `true`.
/// @param value Value of the limit.
- /// @dev EVM selector for this function is: 0x4ad890a8,
- /// or in textual repr: setCollectionLimit(string,uint256)
- function setCollectionLimit(string memory limit, uint256 value) external;
+ /// @dev EVM selector for this function is: 0x88150bd0,
+ /// or in textual repr: setCollectionLimit(uint8,bool,uint256)
+ function setCollectionLimit(
+ CollectionLimits limit,
+ bool status,
+ uint256 value
+ ) external;
/// Get contract address.
/// @dev EVM selector for this function is: 0xf6b4dfb4,
@@ -261,12 +287,12 @@
/// Returns nesting for a collection
/// @dev EVM selector for this function is: 0x22d25bfe,
/// or in textual repr: collectionNestingRestrictedCollectionIds()
- function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);
+ function collectionNestingRestrictedCollectionIds() external view returns (Tuple34 memory);
/// Returns permissions for a collection
/// @dev EVM selector for this function is: 0x5b2eaf4b,
/// or in textual repr: collectionNestingPermissions()
- function collectionNestingPermissions() external view returns (Tuple33[] memory);
+ function collectionNestingPermissions() external view returns (Tuple37[] memory);
/// Set the collection access method.
/// @param mode Access mode
@@ -381,7 +407,7 @@
}
/// @dev anonymous struct
-struct Tuple33 {
+struct Tuple37 {
CollectionPermissions field_0;
bool field_1;
}
@@ -392,11 +418,40 @@
}
/// @dev anonymous struct
-struct Tuple30 {
+struct Tuple34 {
bool field_0;
uint256[] field_1;
}
+/// @dev [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
+enum CollectionLimits {
+ /// @dev How many tokens can a user have on one account.
+ AccountTokenOwnership,
+ /// @dev How many bytes of data are available for sponsorship.
+ SponsoredDataSize,
+ /// @dev In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]
+ SponsoredDataRateLimit,
+ /// @dev How many tokens can be mined into this collection.
+ TokenLimit,
+ /// @dev Timeouts for transfer sponsoring.
+ SponsorTransferTimeout,
+ /// @dev Timeout for sponsoring an approval in passed blocks.
+ SponsorApproveTimeout,
+ /// @dev Whether the collection owner of the collection can send tokens (which belong to other users).
+ OwnerCanTransfer,
+ /// @dev Can the collection owner burn other people's tokens.
+ OwnerCanDestroy,
+ /// @dev Is it possible to send tokens from this collection between users.
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple29 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev anonymous struct
struct Tuple26 {
address field_0;
tests/src/eth/collectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionLimits.test.ts
+++ b/tests/src/eth/collectionLimits.test.ts
@@ -1,6 +1,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {Pallets} from '../util';
import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits} from './util/playgrounds/types';
describe('Can set collection limits', () => {
@@ -44,20 +45,33 @@
transfersEnabled: false,
};
- const collection = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
- await collection.methods.setCollectionLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
- await collection.methods.setCollectionLimit('sponsoredDataSize', limits.sponsoredDataSize).send();
- await collection.methods.setCollectionLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
- await collection.methods.setCollectionLimit('tokenLimit', limits.tokenLimit).send();
- await collection.methods.setCollectionLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
- await collection.methods.setCollectionLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
- await collection.methods.setCollectionLimit('ownerCanTransfer', limits.ownerCanTransfer).send();
- await collection.methods.setCollectionLimit('ownerCanDestroy', limits.ownerCanDestroy).send();
- await collection.methods.setCollectionLimit('transfersEnabled', limits.transfersEnabled).send();
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();
+ await collectionEvm.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();
+ // Check limits from sub:
const data = (await helper.rft.getData(collectionId))!;
expect(data.raw.limits).to.deep.eq(expectedLimits);
expect(await helper.collection.getEffectiveLimits(collectionId)).to.deep.eq(expectedLimits);
+ // Check limits from eth:
+ const limitsEvm = await collectionEvm.methods.collectionLimits().call({from: owner});
+ expect(limitsEvm).to.have.length(9);
+ expect(limitsEvm[0]).to.deep.eq([CollectionLimits.AccountTokenOwnership.toString(), true, limits.accountTokenOwnershipLimit.toString()]);
+ expect(limitsEvm[1]).to.deep.eq([CollectionLimits.SponsoredDataSize.toString(), true, limits.sponsoredDataSize.toString()]);
+ expect(limitsEvm[2]).to.deep.eq([CollectionLimits.SponsoredDataRateLimit.toString(), true, limits.sponsoredDataRateLimit.toString()]);
+ expect(limitsEvm[3]).to.deep.eq([CollectionLimits.TokenLimit.toString(), true, limits.tokenLimit.toString()]);
+ expect(limitsEvm[4]).to.deep.eq([CollectionLimits.SponsorTransferTimeout.toString(), true, limits.sponsorTransferTimeout.toString()]);
+ expect(limitsEvm[5]).to.deep.eq([CollectionLimits.SponsorApproveTimeout.toString(), true, limits.sponsorApproveTimeout.toString()]);
+ expect(limitsEvm[6]).to.deep.eq([CollectionLimits.OwnerCanTransfer.toString(), true, limits.ownerCanTransfer.toString()]);
+ expect(limitsEvm[7]).to.deep.eq([CollectionLimits.OwnerCanDestroy.toString(), true, limits.ownerCanDestroy.toString()]);
+ expect(limitsEvm[8]).to.deep.eq([CollectionLimits.TransferEnabled.toString(), true, limits.transfersEnabled.toString()]);
}));
});
@@ -84,17 +98,48 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress} = await helper.eth.createCollection(testCase.case, owner, 'Limits', 'absolutely anything', 'ISNI', 18);
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
+
+ // Cannot set non-existing limit
await expect(collectionEvm.methods
- .setCollectionLimit('badLimit', '1')
- .call()).to.be.rejectedWith('unknown limit "badLimit"');
-
+ .setCollectionLimit(9, true, 1)
+ .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"');
+
+ // Cannot disable limits
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, false, 200)
+ .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert user can\'t disable limits');
+
await expect(collectionEvm.methods
- .setCollectionLimit(Object.keys(invalidLimits)[0], invalidLimits.accountTokenOwnershipLimit)
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)
.call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
-
+
await expect(collectionEvm.methods
- .setCollectionLimit(Object.keys(invalidLimits)[1], invalidLimits.transfersEnabled)
+ .setCollectionLimit(CollectionLimits.TransferEnabled, true, 3)
.call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
+
+ expect(() => collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.SponsoredDataSize, true, -1).send()).to.throw('value out-of-bounds');
}));
+
+ [
+ {case: 'nft' as const, requiredPallets: []},
+ {case: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {case: 'ft' as const, requiredPallets: []},
+ ].map(testCase =>
+ itEth.ifWithPallets(`Non-owner and non-admin cannot set collection limits for ${testCase.case}`, testCase.requiredPallets || [], async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const nonOwner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createCollection(testCase.case, owner, 'Limits', 'absolutely anything', 'FLO', 18);
+
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
+ .call({from: nonOwner}))
+ .to.be.rejectedWith('NoPermission');
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
+ .send({from: nonOwner}))
+ .to.be.rejected;
+ }));
});
-
\ No newline at end of file
tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -18,6 +18,7 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {Pallets, requirePalletsOrSkip} from '../util';
import {expect, itEth, usingEthPlaygrounds} from './util';
+import { CollectionLimits } from './util/playgrounds/types';
const DECIMALS = 18;
@@ -196,7 +197,7 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -221,7 +222,7 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -17,6 +17,7 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
import {expect, itEth, usingEthPlaygrounds} from './util';
+import { CollectionLimits } from './util/playgrounds/types';
describe('Create NFT collection from EVM', () => {
@@ -207,7 +208,7 @@
}
{
await expect(malfeasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -232,7 +233,7 @@
}
{
await expect(malfeasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -18,6 +18,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {Pallets, requirePalletsOrSkip} from '../util';
import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits} from './util/playgrounds/types';
describe('Create RFT collection from EVM', () => {
@@ -239,7 +240,7 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -264,7 +265,7 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
tests/src/eth/events.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {expect} from 'chai';18import {IKeyringPair} from '@polkadot/types/types';19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';21import {Pallets, requirePalletsOrSkip} from '../util';22import {EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';2324let donor: IKeyringPair;25 26before(async function () {27 await usingEthPlaygrounds(async (_helper, privateKey) => {28 donor = await privateKey({filename: __filename});29 });30});3132function clearEvents(ethEvents: NormalizedEvent[], subEvents: IEvent[]) {33 ethEvents.splice(0);34 subEvents.splice(0);35}3637async function testCollectionCreatedAndDestroy(helper: EthUniqueHelper, mode: TCollectionMode) {38 const owner = await helper.eth.createAccountWithBalance(donor);39 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionCreated', 'CollectionDestroyed']}]);40 const {collectionAddress, events: ethEvents} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');41 await helper.wait.newBlocks(1);42 {43 expect(ethEvents).to.be.like([44 {45 event: 'CollectionCreated',46 args: {47 owner: owner,48 collectionId: collectionAddress,49 },50 },51 ]);52 expect(subEvents).to.be.like([{method: 'CollectionCreated'}]);53 clearEvents(ethEvents, subEvents);54 }55 {56 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);57 const result = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner});58 await helper.wait.newBlocks(1);59 expect(result.events).to.be.like({60 CollectionDestroyed: {61 returnValues: {62 collectionId: collectionAddress,63 },64 },65 });66 expect(subEvents).to.be.like([{method: 'CollectionDestroyed'}]);67 }68 unsubscribe();69}7071async function testCollectionPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {72 const owner = await helper.eth.createAccountWithBalance(donor);73 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');74 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);75 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);76 77 const ethEvents: any = [];78 collectionHelper.events.allEvents((_: any, event: any) => {79 ethEvents.push(event);80 });81 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPropertySet', 'CollectionPropertyDeleted']}]);82 {83 await collection.methods.setCollectionProperties([{key: 'A', value: [0,1,2,3]}]).send({from:owner});84 await helper.wait.newBlocks(1);85 expect(ethEvents).to.be.like([86 {87 event: 'CollectionChanged',88 returnValues: {89 collectionId: collectionAddress,90 },91 },92 ]);93 expect(subEvents).to.be.like([{method: 'CollectionPropertySet'}]);94 clearEvents(ethEvents, subEvents);95 }96 {97 await collection.methods.deleteCollectionProperties(['A']).send({from:owner});98 await helper.wait.newBlocks(1);99 expect(ethEvents).to.be.like([100 {101 event: 'CollectionChanged',102 returnValues: {103 collectionId: collectionAddress,104 },105 },106 ]);107 expect(subEvents).to.be.like([{method: 'CollectionPropertyDeleted'}]);108 }109 unsubscribe();110}111112async function testPropertyPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {113 const owner = await helper.eth.createAccountWithBalance(donor);114 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');115 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);116 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);117 const ethEvents: any = [];118 collectionHelper.events.allEvents((_: any, event: any) => {119 ethEvents.push(event);120 });121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);122 await collection.methods.setTokenPropertyPermissions([123 ['A', [124 [EthTokenPermissions.Mutable, true], 125 [EthTokenPermissions.TokenOwner, true], 126 [EthTokenPermissions.CollectionAdmin, true]],127 ],128 ]).send({from: owner});129 await helper.wait.newBlocks(1);130 expect(ethEvents).to.be.like([131 {132 event: 'CollectionChanged',133 returnValues: {134 collectionId: collectionAddress,135 },136 },137 ]);138 expect(subEvents).to.be.like([{method: 'PropertyPermissionSet'}]);139 unsubscribe();140}141142async function testAllowListAddressAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {143 const owner = await helper.eth.createAccountWithBalance(donor);144 const user = helper.ethCrossAccount.createAccount();145 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');146 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);147 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);148 const ethEvents: any[] = [];149 collectionHelper.events.allEvents((_: any, event: any) => {150 ethEvents.push(event);151 });152153 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['AllowListAddressAdded', 'AllowListAddressRemoved']}]);154 {155 await collection.methods.addToCollectionAllowListCross(user).send({from: owner});156 await helper.wait.newBlocks(1);157 expect(ethEvents).to.be.like([158 {159 event: 'CollectionChanged',160 returnValues: {161 collectionId: collectionAddress,162 },163 },164 ]);165 expect(subEvents).to.be.like([{method: 'AllowListAddressAdded'}]);166 clearEvents(ethEvents, subEvents);167 }168 {169 await collection.methods.removeFromCollectionAllowListCross(user).send({from: owner});170 await helper.wait.newBlocks(1);171 expect(ethEvents.length).to.be.eq(1);172 expect(ethEvents).to.be.like([173 {174 event: 'CollectionChanged',175 returnValues: {176 collectionId: collectionAddress,177 },178 },179 ]);180 expect(subEvents).to.be.like([{method: 'AllowListAddressRemoved'}]);181 }182 unsubscribe();183}184185async function testCollectionAdminAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {186 const owner = await helper.eth.createAccountWithBalance(donor);187 const user = helper.ethCrossAccount.createAccount();188 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');189 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);190 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);191 const ethEvents: any = [];192 collectionHelper.events.allEvents((_: any, event: any) => {193 ethEvents.push(event);194 });195 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionAdminAdded', 'CollectionAdminRemoved']}]);196 {197 await collection.methods.addCollectionAdminCross(user).send({from: owner});198 await helper.wait.newBlocks(1);199 expect(ethEvents).to.be.like([200 {201 event: 'CollectionChanged',202 returnValues: {203 collectionId: collectionAddress,204 },205 },206 ]);207 expect(subEvents).to.be.like([{method: 'CollectionAdminAdded'}]);208 clearEvents(ethEvents, subEvents);209 }210 {211 await collection.methods.removeCollectionAdminCross(user).send({from: owner});212 await helper.wait.newBlocks(1);213 expect(ethEvents).to.be.like([214 {215 event: 'CollectionChanged',216 returnValues: {217 collectionId: collectionAddress,218 },219 },220 ]);221 expect(subEvents).to.be.like([{method: 'CollectionAdminRemoved'}]);222 }223 unsubscribe();224}225226async function testCollectionLimitSet(helper: EthUniqueHelper, mode: TCollectionMode) {227 const owner = await helper.eth.createAccountWithBalance(donor);228 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');229 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);230 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);231 const ethEvents: any = [];232 collectionHelper.events.allEvents((_: any, event: any) => {233 ethEvents.push(event);234 });235 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);236 {237 await collection.methods.setCollectionLimit('ownerCanTransfer', 0n).send({from: owner});238 await helper.wait.newBlocks(1);239 expect(ethEvents).to.be.like([240 {241 event: 'CollectionChanged',242 returnValues: {243 collectionId: collectionAddress,244 },245 },246 ]);247 expect(subEvents).to.be.like([{method: 'CollectionLimitSet'}]);248 }249 unsubscribe();250}251252async function testCollectionOwnerChanged(helper: EthUniqueHelper, mode: TCollectionMode) {253 const owner = await helper.eth.createAccountWithBalance(donor);254 const newOwner = helper.ethCrossAccount.createAccount();255 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');256 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);257 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);258 const ethEvents: any = [];259 collectionHelper.events.allEvents((_: any, event: any) => {260 ethEvents.push(event);261 });262 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnerChanged']}]);263 {264 await collection.methods.changeCollectionOwnerCross(newOwner).send({from: owner});265 await helper.wait.newBlocks(1);266 expect(ethEvents).to.be.like([267 {268 event: 'CollectionChanged',269 returnValues: {270 collectionId: collectionAddress,271 },272 },273 ]);274 expect(subEvents).to.be.like([{method: 'CollectionOwnerChanged'}]);275 }276 unsubscribe();277}278279async function testCollectionPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {280 const owner = await helper.eth.createAccountWithBalance(donor);281 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');282 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);283 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);284 const ethEvents: any = [];285 collectionHelper.events.allEvents((_: any, event: any) => {286 ethEvents.push(event);287 });288 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPermissionSet']}]);289 {290 await collection.methods.setCollectionMintMode(true).send({from: owner});291 await helper.wait.newBlocks(1);292 expect(ethEvents).to.be.like([293 {294 event: 'CollectionChanged',295 returnValues: {296 collectionId: collectionAddress,297 },298 },299 ]);300 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);301 clearEvents(ethEvents, subEvents);302 }303 {304 await collection.methods.setCollectionAccess(1).send({from: owner});305 await helper.wait.newBlocks(1);306 expect(ethEvents).to.be.like([307 {308 event: 'CollectionChanged',309 returnValues: {310 collectionId: collectionAddress,311 },312 },313 ]);314 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);315 }316 unsubscribe();317}318319async function testCollectionSponsorSetAndConfirmedAndThenRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {320 const owner = await helper.eth.createAccountWithBalance(donor);321 const sponsor = await helper.ethCrossAccount.createAccountWithBalance(donor);322 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');323 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);324 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);325 const ethEvents: any = [];326 collectionHelper.events.allEvents((_: any, event: any) => {327 ethEvents.push(event);328 });329 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{330 section: 'common', names: ['CollectionSponsorSet', 'SponsorshipConfirmed', 'CollectionSponsorRemoved',331 ]}]);332 {333 await collection.methods.setCollectionSponsorCross(sponsor).send({from: owner});334 await helper.wait.newBlocks(1);335 expect(ethEvents).to.be.like([336 {337 event: 'CollectionChanged',338 returnValues: {339 collectionId: collectionAddress,340 },341 },342 ]);343 expect(subEvents).to.be.like([{method: 'CollectionSponsorSet'}]);344 clearEvents(ethEvents, subEvents);345 }346 {347 await collection.methods.confirmCollectionSponsorship().send({from: sponsor.eth});348 await helper.wait.newBlocks(1);349 expect(ethEvents).to.be.like([350 {351 event: 'CollectionChanged',352 returnValues: {353 collectionId: collectionAddress,354 },355 },356 ]);357 expect(subEvents).to.be.like([{method: 'SponsorshipConfirmed'}]);358 clearEvents(ethEvents, subEvents);359 }360 {361 await collection.methods.removeCollectionSponsor().send({from: owner});362 await helper.wait.newBlocks(1);363 expect(ethEvents).to.be.like([364 {365 event: 'CollectionChanged',366 returnValues: {367 collectionId: collectionAddress,368 },369 },370 ]);371 expect(subEvents).to.be.like([{method: 'CollectionSponsorRemoved'}]);372 }373 unsubscribe();374}375376async function testTokenPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {377 const owner = await helper.eth.createAccountWithBalance(donor);378 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');379 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);380 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);381 const result = await collection.methods.mint(owner).send({from: owner});382 const tokenId = result.events.Transfer.returnValues.tokenId;383 await collection.methods.setTokenPropertyPermissions([384 ['A', [385 [EthTokenPermissions.Mutable, true], 386 [EthTokenPermissions.TokenOwner, true], 387 [EthTokenPermissions.CollectionAdmin, true]],388 ],389 ]).send({from: owner});390391392 const ethEvents: any = [];393 collectionHelper.events.allEvents((_: any, event: any) => {394 ethEvents.push(event);395 });396 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);397 {398 await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});399 await helper.wait.newBlocks(1);400 expect(ethEvents).to.be.like([401 {402 event: 'TokenChanged',403 returnValues: {404 collectionId: collectionAddress,405 },406 },407 ]);408 expect(subEvents).to.be.like([{method: 'TokenPropertySet'}]);409 clearEvents(ethEvents, subEvents);410 }411 {412 await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});413 await helper.wait.newBlocks(1);414 expect(ethEvents).to.be.like([415 {416 event: 'TokenChanged',417 returnValues: {418 collectionId: collectionAddress,419 },420 },421 ]);422 expect(subEvents).to.be.like([{method: 'TokenPropertyDeleted'}]);423 }424 unsubscribe();425}426427describe('[FT] Sync sub & eth events', () => {428 const mode: TCollectionMode = 'ft';429430 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {431 await testCollectionCreatedAndDestroy(helper, mode);432 });433434 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {435 await testCollectionPropertySetAndDeleted(helper, mode);436 });437 438 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {439 await testAllowListAddressAddedAndRemoved(helper, mode);440 });441 442 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {443 await testCollectionAdminAddedAndRemoved(helper, mode);444 });445 446 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {447 await testCollectionLimitSet(helper, mode);448 });449 450 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {451 await testCollectionOwnerChanged(helper, mode);452 });453 454 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {455 await testCollectionPermissionSet(helper, mode);456 });457458 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {459 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);460 });461});462463describe('[NFT] Sync sub & eth events', () => {464 const mode: TCollectionMode = 'nft';465466 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {467 await testCollectionCreatedAndDestroy(helper, mode);468 });469470 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {471 await testCollectionPropertySetAndDeleted(helper, mode);472 });473 474 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {475 await testPropertyPermissionSet(helper, mode);476 });477 478 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {479 await testAllowListAddressAddedAndRemoved(helper, mode);480 });481 482 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {483 await testCollectionAdminAddedAndRemoved(helper, mode);484 });485 486 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {487 await testCollectionLimitSet(helper, mode);488 });489 490 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {491 await testCollectionOwnerChanged(helper, mode);492 });493 494 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {495 await testCollectionPermissionSet(helper, mode);496 });497498 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {499 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);500 });501 502 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {503 await testTokenPropertySetAndDeleted(helper, mode);504 });505});506507describe('[RFT] Sync sub & eth events', () => {508 const mode: TCollectionMode = 'rft';509510 before(async function() {511 await usingEthPlaygrounds(async (helper, privateKey) => {512 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);513 const _donor = await privateKey({filename: __filename});514 });515 });516517 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {518 await testCollectionCreatedAndDestroy(helper, mode);519 });520521 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {522 await testCollectionPropertySetAndDeleted(helper, mode);523 });524 525 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {526 await testPropertyPermissionSet(helper, mode);527 });528 529 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {530 await testAllowListAddressAddedAndRemoved(helper, mode);531 });532 533 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {534 await testCollectionAdminAddedAndRemoved(helper, mode);535 });536 537 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {538 await testCollectionLimitSet(helper, mode);539 });540 541 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {542 await testCollectionOwnerChanged(helper, mode);543 });544 545 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {546 await testCollectionPermissionSet(helper, mode);547 });548549 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {550 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);551 });552 553 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {554 await testTokenPropertySetAndDeleted(helper, mode);555 });556});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {expect} from 'chai';18import {IKeyringPair} from '@polkadot/types/types';19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';21import {Pallets, requirePalletsOrSkip} from '../util';22import {CollectionLimits, EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';2324let donor: IKeyringPair;25 26before(async function () {27 await usingEthPlaygrounds(async (_helper, privateKey) => {28 donor = await privateKey({filename: __filename});29 });30});3132function clearEvents(ethEvents: NormalizedEvent[], subEvents: IEvent[]) {33 ethEvents.splice(0);34 subEvents.splice(0);35}3637async function testCollectionCreatedAndDestroy(helper: EthUniqueHelper, mode: TCollectionMode) {38 const owner = await helper.eth.createAccountWithBalance(donor);39 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionCreated', 'CollectionDestroyed']}]);40 const {collectionAddress, events: ethEvents} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');41 await helper.wait.newBlocks(1);42 {43 expect(ethEvents).to.be.like([44 {45 event: 'CollectionCreated',46 args: {47 owner: owner,48 collectionId: collectionAddress,49 },50 },51 ]);52 expect(subEvents).to.be.like([{method: 'CollectionCreated'}]);53 clearEvents(ethEvents, subEvents);54 }55 {56 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);57 const result = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner});58 await helper.wait.newBlocks(1);59 expect(result.events).to.be.like({60 CollectionDestroyed: {61 returnValues: {62 collectionId: collectionAddress,63 },64 },65 });66 expect(subEvents).to.be.like([{method: 'CollectionDestroyed'}]);67 }68 unsubscribe();69}7071async function testCollectionPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {72 const owner = await helper.eth.createAccountWithBalance(donor);73 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');74 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);75 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);76 77 const ethEvents: any = [];78 collectionHelper.events.allEvents((_: any, event: any) => {79 ethEvents.push(event);80 });81 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPropertySet', 'CollectionPropertyDeleted']}]);82 {83 await collection.methods.setCollectionProperties([{key: 'A', value: [0,1,2,3]}]).send({from:owner});84 await helper.wait.newBlocks(1);85 expect(ethEvents).to.be.like([86 {87 event: 'CollectionChanged',88 returnValues: {89 collectionId: collectionAddress,90 },91 },92 ]);93 expect(subEvents).to.be.like([{method: 'CollectionPropertySet'}]);94 clearEvents(ethEvents, subEvents);95 }96 {97 await collection.methods.deleteCollectionProperties(['A']).send({from:owner});98 await helper.wait.newBlocks(1);99 expect(ethEvents).to.be.like([100 {101 event: 'CollectionChanged',102 returnValues: {103 collectionId: collectionAddress,104 },105 },106 ]);107 expect(subEvents).to.be.like([{method: 'CollectionPropertyDeleted'}]);108 }109 unsubscribe();110}111112async function testPropertyPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {113 const owner = await helper.eth.createAccountWithBalance(donor);114 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');115 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);116 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);117 const ethEvents: any = [];118 collectionHelper.events.allEvents((_: any, event: any) => {119 ethEvents.push(event);120 });121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);122 await collection.methods.setTokenPropertyPermissions([123 ['A', [124 [EthTokenPermissions.Mutable, true], 125 [EthTokenPermissions.TokenOwner, true], 126 [EthTokenPermissions.CollectionAdmin, true]],127 ],128 ]).send({from: owner});129 await helper.wait.newBlocks(1);130 expect(ethEvents).to.be.like([131 {132 event: 'CollectionChanged',133 returnValues: {134 collectionId: collectionAddress,135 },136 },137 ]);138 expect(subEvents).to.be.like([{method: 'PropertyPermissionSet'}]);139 unsubscribe();140}141142async function testAllowListAddressAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {143 const owner = await helper.eth.createAccountWithBalance(donor);144 const user = helper.ethCrossAccount.createAccount();145 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');146 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);147 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);148 const ethEvents: any[] = [];149 collectionHelper.events.allEvents((_: any, event: any) => {150 ethEvents.push(event);151 });152153 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['AllowListAddressAdded', 'AllowListAddressRemoved']}]);154 {155 await collection.methods.addToCollectionAllowListCross(user).send({from: owner});156 await helper.wait.newBlocks(1);157 expect(ethEvents).to.be.like([158 {159 event: 'CollectionChanged',160 returnValues: {161 collectionId: collectionAddress,162 },163 },164 ]);165 expect(subEvents).to.be.like([{method: 'AllowListAddressAdded'}]);166 clearEvents(ethEvents, subEvents);167 }168 {169 await collection.methods.removeFromCollectionAllowListCross(user).send({from: owner});170 await helper.wait.newBlocks(1);171 expect(ethEvents.length).to.be.eq(1);172 expect(ethEvents).to.be.like([173 {174 event: 'CollectionChanged',175 returnValues: {176 collectionId: collectionAddress,177 },178 },179 ]);180 expect(subEvents).to.be.like([{method: 'AllowListAddressRemoved'}]);181 }182 unsubscribe();183}184185async function testCollectionAdminAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {186 const owner = await helper.eth.createAccountWithBalance(donor);187 const user = helper.ethCrossAccount.createAccount();188 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');189 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);190 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);191 const ethEvents: any = [];192 collectionHelper.events.allEvents((_: any, event: any) => {193 ethEvents.push(event);194 });195 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionAdminAdded', 'CollectionAdminRemoved']}]);196 {197 await collection.methods.addCollectionAdminCross(user).send({from: owner});198 await helper.wait.newBlocks(1);199 expect(ethEvents).to.be.like([200 {201 event: 'CollectionChanged',202 returnValues: {203 collectionId: collectionAddress,204 },205 },206 ]);207 expect(subEvents).to.be.like([{method: 'CollectionAdminAdded'}]);208 clearEvents(ethEvents, subEvents);209 }210 {211 await collection.methods.removeCollectionAdminCross(user).send({from: owner});212 await helper.wait.newBlocks(1);213 expect(ethEvents).to.be.like([214 {215 event: 'CollectionChanged',216 returnValues: {217 collectionId: collectionAddress,218 },219 },220 ]);221 expect(subEvents).to.be.like([{method: 'CollectionAdminRemoved'}]);222 }223 unsubscribe();224}225226async function testCollectionLimitSet(helper: EthUniqueHelper, mode: TCollectionMode) {227 const owner = await helper.eth.createAccountWithBalance(donor);228 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');229 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);230 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);231 const ethEvents: any = [];232 collectionHelper.events.allEvents((_: any, event: any) => {233 ethEvents.push(event);234 });235 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);236 {237 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, 0).send({from: owner});238 await helper.wait.newBlocks(1);239 expect(ethEvents).to.be.like([240 {241 event: 'CollectionChanged',242 returnValues: {243 collectionId: collectionAddress,244 },245 },246 ]);247 expect(subEvents).to.be.like([{method: 'CollectionLimitSet'}]);248 }249 unsubscribe();250}251252async function testCollectionOwnerChanged(helper: EthUniqueHelper, mode: TCollectionMode) {253 const owner = await helper.eth.createAccountWithBalance(donor);254 const newOwner = helper.ethCrossAccount.createAccount();255 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');256 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);257 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);258 const ethEvents: any = [];259 collectionHelper.events.allEvents((_: any, event: any) => {260 ethEvents.push(event);261 });262 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnerChanged']}]);263 {264 await collection.methods.changeCollectionOwnerCross(newOwner).send({from: owner});265 await helper.wait.newBlocks(1);266 expect(ethEvents).to.be.like([267 {268 event: 'CollectionChanged',269 returnValues: {270 collectionId: collectionAddress,271 },272 },273 ]);274 expect(subEvents).to.be.like([{method: 'CollectionOwnerChanged'}]);275 }276 unsubscribe();277}278279async function testCollectionPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {280 const owner = await helper.eth.createAccountWithBalance(donor);281 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');282 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);283 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);284 const ethEvents: any = [];285 collectionHelper.events.allEvents((_: any, event: any) => {286 ethEvents.push(event);287 });288 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPermissionSet']}]);289 {290 await collection.methods.setCollectionMintMode(true).send({from: owner});291 await helper.wait.newBlocks(1);292 expect(ethEvents).to.be.like([293 {294 event: 'CollectionChanged',295 returnValues: {296 collectionId: collectionAddress,297 },298 },299 ]);300 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);301 clearEvents(ethEvents, subEvents);302 }303 {304 await collection.methods.setCollectionAccess(1).send({from: owner});305 await helper.wait.newBlocks(1);306 expect(ethEvents).to.be.like([307 {308 event: 'CollectionChanged',309 returnValues: {310 collectionId: collectionAddress,311 },312 },313 ]);314 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);315 }316 unsubscribe();317}318319async function testCollectionSponsorSetAndConfirmedAndThenRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {320 const owner = await helper.eth.createAccountWithBalance(donor);321 const sponsor = await helper.ethCrossAccount.createAccountWithBalance(donor);322 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');323 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);324 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);325 const ethEvents: any = [];326 collectionHelper.events.allEvents((_: any, event: any) => {327 ethEvents.push(event);328 });329 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{330 section: 'common', names: ['CollectionSponsorSet', 'SponsorshipConfirmed', 'CollectionSponsorRemoved',331 ]}]);332 {333 await collection.methods.setCollectionSponsorCross(sponsor).send({from: owner});334 await helper.wait.newBlocks(1);335 expect(ethEvents).to.be.like([336 {337 event: 'CollectionChanged',338 returnValues: {339 collectionId: collectionAddress,340 },341 },342 ]);343 expect(subEvents).to.be.like([{method: 'CollectionSponsorSet'}]);344 clearEvents(ethEvents, subEvents);345 }346 {347 await collection.methods.confirmCollectionSponsorship().send({from: sponsor.eth});348 await helper.wait.newBlocks(1);349 expect(ethEvents).to.be.like([350 {351 event: 'CollectionChanged',352 returnValues: {353 collectionId: collectionAddress,354 },355 },356 ]);357 expect(subEvents).to.be.like([{method: 'SponsorshipConfirmed'}]);358 clearEvents(ethEvents, subEvents);359 }360 {361 await collection.methods.removeCollectionSponsor().send({from: owner});362 await helper.wait.newBlocks(1);363 expect(ethEvents).to.be.like([364 {365 event: 'CollectionChanged',366 returnValues: {367 collectionId: collectionAddress,368 },369 },370 ]);371 expect(subEvents).to.be.like([{method: 'CollectionSponsorRemoved'}]);372 }373 unsubscribe();374}375376async function testTokenPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {377 const owner = await helper.eth.createAccountWithBalance(donor);378 const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');379 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);380 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);381 const result = await collection.methods.mint(owner).send({from: owner});382 const tokenId = result.events.Transfer.returnValues.tokenId;383 await collection.methods.setTokenPropertyPermissions([384 ['A', [385 [EthTokenPermissions.Mutable, true], 386 [EthTokenPermissions.TokenOwner, true], 387 [EthTokenPermissions.CollectionAdmin, true]],388 ],389 ]).send({from: owner});390391392 const ethEvents: any = [];393 collectionHelper.events.allEvents((_: any, event: any) => {394 ethEvents.push(event);395 });396 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);397 {398 await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});399 await helper.wait.newBlocks(1);400 expect(ethEvents).to.be.like([401 {402 event: 'TokenChanged',403 returnValues: {404 collectionId: collectionAddress,405 },406 },407 ]);408 expect(subEvents).to.be.like([{method: 'TokenPropertySet'}]);409 clearEvents(ethEvents, subEvents);410 }411 {412 await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});413 await helper.wait.newBlocks(1);414 expect(ethEvents).to.be.like([415 {416 event: 'TokenChanged',417 returnValues: {418 collectionId: collectionAddress,419 },420 },421 ]);422 expect(subEvents).to.be.like([{method: 'TokenPropertyDeleted'}]);423 }424 unsubscribe();425}426427describe('[FT] Sync sub & eth events', () => {428 const mode: TCollectionMode = 'ft';429430 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {431 await testCollectionCreatedAndDestroy(helper, mode);432 });433434 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {435 await testCollectionPropertySetAndDeleted(helper, mode);436 });437 438 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {439 await testAllowListAddressAddedAndRemoved(helper, mode);440 });441 442 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {443 await testCollectionAdminAddedAndRemoved(helper, mode);444 });445 446 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {447 await testCollectionLimitSet(helper, mode);448 });449 450 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {451 await testCollectionOwnerChanged(helper, mode);452 });453 454 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {455 await testCollectionPermissionSet(helper, mode);456 });457458 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {459 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);460 });461});462463describe('[NFT] Sync sub & eth events', () => {464 const mode: TCollectionMode = 'nft';465466 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {467 await testCollectionCreatedAndDestroy(helper, mode);468 });469470 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {471 await testCollectionPropertySetAndDeleted(helper, mode);472 });473 474 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {475 await testPropertyPermissionSet(helper, mode);476 });477 478 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {479 await testAllowListAddressAddedAndRemoved(helper, mode);480 });481 482 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {483 await testCollectionAdminAddedAndRemoved(helper, mode);484 });485 486 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {487 await testCollectionLimitSet(helper, mode);488 });489 490 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {491 await testCollectionOwnerChanged(helper, mode);492 });493 494 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {495 await testCollectionPermissionSet(helper, mode);496 });497498 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {499 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);500 });501 502 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {503 await testTokenPropertySetAndDeleted(helper, mode);504 });505});506507describe('[RFT] Sync sub & eth events', () => {508 const mode: TCollectionMode = 'rft';509510 before(async function() {511 await usingEthPlaygrounds(async (helper, privateKey) => {512 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);513 const _donor = await privateKey({filename: __filename});514 });515 });516517 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {518 await testCollectionCreatedAndDestroy(helper, mode);519 });520521 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {522 await testCollectionPropertySetAndDeleted(helper, mode);523 });524 525 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {526 await testPropertyPermissionSet(helper, mode);527 });528 529 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {530 await testAllowListAddressAddedAndRemoved(helper, mode);531 });532 533 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {534 await testCollectionAdminAddedAndRemoved(helper, mode);535 });536 537 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {538 await testCollectionLimitSet(helper, mode);539 });540 541 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {542 await testCollectionOwnerChanged(helper, mode);543 });544 545 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {546 await testCollectionPermissionSet(helper, mode);547 });548549 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {550 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);551 });552 553 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {554 await testTokenPropertySetAndDeleted(helper, mode);555 });556});tests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/types.ts
+++ b/tests/src/eth/util/playgrounds/types.ts
@@ -24,4 +24,15 @@
Mutable,
TokenOwner,
CollectionAdmin
-}
\ No newline at end of file
+}
+export enum CollectionLimits {
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled
+}
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -84,6 +84,7 @@
);
} else if (chain.eq('UNIQUE')) {
// Insert Unique additional pallets here
+ requiredPallets.push(foreignAssets);
}
});
});