difftreelog
added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
in: master
15 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,101 @@
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
+ .map(|limit| {
+ (
+ EvmCollectionLimits::SponsoredDataRateLimit,
+ match limit {
+ SponsoringRateLimit::Blocks(_) => true,
+ _ => false,
+ },
+ match limit {
+ SponsoringRateLimit::Blocks(blocks) => blocks.into(),
+ _ => Default::default(),
+ },
+ )
+ })
+ .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:
@@ -318,9 +414,19 @@
/// "transfersEnabled"
/// @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 +444,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);
@@ -778,3 +884,31 @@
})
}
}
+
+fn convert_value_limit<V: Into<uint256> + Copy>(
+ limit: EvmCollectionLimits,
+ value: &Option<V>,
+) -> (EvmCollectionLimits, bool, uint256) {
+ value
+ .map(|v| (limit, true, v.into()))
+ .unwrap_or((limit, false, Default::default()))
+}
+
+fn 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()))
+}
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -155,6 +155,20 @@
}
}
}
+#[derive(Debug, Default, Clone, Copy, AbiCoder)]
+#[repr(u8)]
+pub enum CollectionLimits {
+ #[default]
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled,
+}
#[derive(Default, Debug, Clone, Copy, AbiCoder)]
#[repr(u8)]
pub enum CollectionPermissions {
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -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:
@@ -171,11 +192,16 @@
/// "ownerCanDestroy",
/// "transfersEnabled"
/// @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;
}
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -291,6 +291,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:
@@ -304,11 +325,16 @@
/// "ownerCanDestroy",
/// "transfersEnabled"
/// @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;
}
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -292,6 +292,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:
@@ -305,11 +326,16 @@
/// "ownerCanDestroy",
/// "transfersEnabled"
/// @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;
}
tests/src/eth/abi/fungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -208,11 +208,16 @@
},
{
"inputs": [],
+<<<<<<< HEAD
"name": "collectionNestingPermissions",
+=======
+ "name": "collectionLimits",
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
"outputs": [
{
"components": [
{
+<<<<<<< HEAD
"internalType": "enum CollectionPermissions",
"name": "field_0",
"type": "uint8"
@@ -220,6 +225,16 @@
{ "internalType": "bool", "name": "field_1", "type": "bool" }
],
"internalType": "struct Tuple24[]",
+=======
+ "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[]",
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
"name": "",
"type": "tuple[]"
}
@@ -229,6 +244,7 @@
},
{
"inputs": [],
+<<<<<<< HEAD
"name": "collectionNestingRestrictedCollectionIds",
"outputs": [
{
@@ -250,6 +266,8 @@
},
{
"inputs": [],
+=======
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
"name": "collectionOwner",
"outputs": [
{
@@ -453,7 +471,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
@@ -607,7 +607,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/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -589,7 +589,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/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,11 @@
}
/// @title A contract that allows you to work with collections.
+<<<<<<< HEAD
/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+=======
+/// @dev the ERC-165 identifier for this interface is 0xf8ebdec0
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -104,6 +108,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:
@@ -117,9 +138,13 @@
/// "ownerCanDestroy",
/// "transfersEnabled"
/// @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,
@@ -288,6 +313,7 @@
uint256 sub;
}
+<<<<<<< HEAD
/// @dev anonymous struct
struct Tuple23 {
CollectionPermissions field_0;
@@ -303,6 +329,25 @@
struct Tuple20 {
bool field_0;
uint256[] field_1;
+=======
+enum CollectionLimits {
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple19 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
}
/// @dev Property struct
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -104,7 +104,11 @@
}
/// @title A contract that allows you to work with collections.
+<<<<<<< HEAD
/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
+=======
+/// @dev the ERC-165 identifier for this interface is 0xf8ebdec0
+>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
interface Collection is Dummy, ERC165 {
// /// Set collection property.
// ///
@@ -195,6 +199,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:
@@ -208,9 +229,13 @@
/// "ownerCanDestroy",
/// "transfersEnabled"
/// @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,
@@ -379,6 +404,25 @@
uint256 sub;
}
+enum CollectionLimits {
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled
+}
+
+/// @dev anonymous struct
+struct Tuple30 {
+ CollectionLimits field_0;
+ bool field_1;
+ uint256 field_2;
+}
+
/// @dev anonymous struct
struct Tuple34 {
CollectionPermissions field_0;
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56/// @dev common stubs holder7interface Dummy {89}1011interface ERC165 is Dummy {12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}1415/// @title A contract that allows to set and delete token properties and change token property permissions.16/// @dev the ERC-165 identifier for this interface is 0xde0695c217interface TokenProperties is Dummy, ERC165 {18 // /// @notice Set permissions for token property.19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.20 // /// @param key Property key.21 // /// @param isMutable Permission to mutate property.22 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.23 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.24 // /// @dev EVM selector for this function is: 0x222d97fa,25 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)26 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) external;2728 /// @notice Set permissions for token property.29 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.30 /// @param permissions Permissions for keys.31 /// @dev EVM selector for this function is: 0xbd92983a,32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])33 function setTokenPropertyPermissions(Tuple47[] memory permissions) external;3435 /// @notice Get permissions for token properties.36 /// @dev EVM selector for this function is: 0xf23d7790,37 /// or in textual repr: tokenPropertyPermissions()38 function tokenPropertyPermissions() external view returns (Tuple47[] memory);3940 // /// @notice Set token property value.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.42 // /// @param tokenId ID of the token.43 // /// @param key Property key.44 // /// @param value Property value.45 // /// @dev EVM selector for this function is: 0x1752d67b,46 // /// or in textual repr: setProperty(uint256,string,bytes)47 // function setProperty(uint256 tokenId, string memory key, bytes memory value) external;4849 /// @notice Set token properties value.50 /// @dev Throws error if `msg.sender` has no permission to edit the property.51 /// @param tokenId ID of the token.52 /// @param properties settable properties53 /// @dev EVM selector for this function is: 0x14ed3a6e,54 /// or in textual repr: setProperties(uint256,(string,bytes)[])55 function setProperties(uint256 tokenId, Property[] memory properties) external;5657 // /// @notice Delete token property value.58 // /// @dev Throws error if `msg.sender` has no permission to edit the property.59 // /// @param tokenId ID of the token.60 // /// @param key Property key.61 // /// @dev EVM selector for this function is: 0x066111d1,62 // /// or in textual repr: deleteProperty(uint256,string)63 // function deleteProperty(uint256 tokenId, string memory key) external;6465 /// @notice Delete token properties value.66 /// @dev Throws error if `msg.sender` has no permission to edit the property.67 /// @param tokenId ID of the token.68 /// @param keys Properties key.69 /// @dev EVM selector for this function is: 0xc472d371,70 /// or in textual repr: deleteProperties(uint256,string[])71 function deleteProperties(uint256 tokenId, string[] memory keys) external;7273 /// @notice Get token property value.74 /// @dev Throws error if key not found75 /// @param tokenId ID of the token.76 /// @param key Property key.77 /// @return Property value bytes78 /// @dev EVM selector for this function is: 0x7228c327,79 /// or in textual repr: property(uint256,string)80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);81}8283/// @dev Property struct84struct Property {85 string key;86 bytes value;87}8889enum EthTokenPermissions {90 Mutable,91 TokenOwner,92 CollectionAdmin93}9495/// @dev anonymous struct96struct Tuple47 {97 string field_0;98 Tuple45[] field_1;99}100101/// @dev anonymous struct102struct Tuple45 {103 EthTokenPermissions field_0;104 bool field_1;105}106107/// @title A contract that allows you to work with collections.108/// @dev the ERC-165 identifier for this interface is 0xb5e1747f109interface Collection is Dummy, ERC165 {110 // /// Set collection property.111 // ///112 // /// @param key Property key.113 // /// @param value Propery value.114 // /// @dev EVM selector for this function is: 0x2f073f66,115 // /// or in textual repr: setCollectionProperty(string,bytes)116 // function setCollectionProperty(string memory key, bytes memory value) external;117118 /// Set collection properties.119 ///120 /// @param properties Vector of properties key/value pair.121 /// @dev EVM selector for this function is: 0x50b26b2a,122 /// or in textual repr: setCollectionProperties((string,bytes)[])123 function setCollectionProperties(Property[] memory properties) external;124125 // /// Delete collection property.126 // ///127 // /// @param key Property key.128 // /// @dev EVM selector for this function is: 0x7b7debce,129 // /// or in textual repr: deleteCollectionProperty(string)130 // function deleteCollectionProperty(string memory key) external;131132 /// Delete collection properties.133 ///134 /// @param keys Properties keys.135 /// @dev EVM selector for this function is: 0xee206ee3,136 /// or in textual repr: deleteCollectionProperties(string[])137 function deleteCollectionProperties(string[] memory keys) external;138139 /// Get collection property.140 ///141 /// @dev Throws error if key not found.142 ///143 /// @param key Property key.144 /// @return bytes The property corresponding to the key.145 /// @dev EVM selector for this function is: 0xcf24fd6d,146 /// or in textual repr: collectionProperty(string)147 function collectionProperty(string memory key) external view returns (bytes memory);148149 /// Get collection properties.150 ///151 /// @param keys Properties keys. Empty keys for all propertyes.152 /// @return Vector of properties key/value pairs.153 /// @dev EVM selector for this function is: 0x285fb8e6,154 /// or in textual repr: collectionProperties(string[])155 function collectionProperties(string[] memory keys) external view returns (Property[] memory);156157 // /// Set the sponsor of the collection.158 // ///159 // /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.160 // ///161 // /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.162 // /// @dev EVM selector for this function is: 0x7623402e,163 // /// or in textual repr: setCollectionSponsor(address)164 // function setCollectionSponsor(address sponsor) external;165166 /// Set the sponsor of the collection.167 ///168 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.169 ///170 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.171 /// @dev EVM selector for this function is: 0x84a1d5a8,172 /// or in textual repr: setCollectionSponsorCross((address,uint256))173 function setCollectionSponsorCross(EthCrossAccount memory sponsor) external;174175 /// Whether there is a pending sponsor.176 /// @dev EVM selector for this function is: 0x058ac185,177 /// or in textual repr: hasCollectionPendingSponsor()178 function hasCollectionPendingSponsor() external view returns (bool);179180 /// Collection sponsorship confirmation.181 ///182 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.183 /// @dev EVM selector for this function is: 0x3c50e97a,184 /// or in textual repr: confirmCollectionSponsorship()185 function confirmCollectionSponsorship() external;186187 /// Remove collection sponsor.188 /// @dev EVM selector for this function is: 0x6e0326a3,189 /// or in textual repr: removeCollectionSponsor()190 function removeCollectionSponsor() external;191192 /// Get current sponsor.193 ///194 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.195 /// @dev EVM selector for this function is: 0x6ec0a9f1,196 /// or in textual repr: collectionSponsor()197 function collectionSponsor() external view returns (Tuple26 memory);198199 /// Set limits for the collection.200 /// @dev Throws error if limit not found.201 /// @param limit Name of the limit. Valid names:202 /// "accountTokenOwnershipLimit",203 /// "sponsoredDataSize",204 /// "sponsoredDataRateLimit",205 /// "tokenLimit",206 /// "sponsorTransferTimeout",207 /// "sponsorApproveTimeout"208 /// "ownerCanTransfer",209 /// "ownerCanDestroy",210 /// "transfersEnabled"211 /// @param value Value of the limit.212 /// @dev EVM selector for this function is: 0x4ad890a8,213 /// or in textual repr: setCollectionLimit(string,uint256)214 function setCollectionLimit(string memory limit, uint256 value) external;215216 /// Get contract address.217 /// @dev EVM selector for this function is: 0xf6b4dfb4,218 /// or in textual repr: contractAddress()219 function contractAddress() external view returns (address);220221 /// Add collection admin.222 /// @param newAdmin Cross account administrator address.223 /// @dev EVM selector for this function is: 0x859aa7d6,224 /// or in textual repr: addCollectionAdminCross((address,uint256))225 function addCollectionAdminCross(EthCrossAccount memory newAdmin) external;226227 /// Remove collection admin.228 /// @param admin Cross account administrator address.229 /// @dev EVM selector for this function is: 0x6c0cd173,230 /// or in textual repr: removeCollectionAdminCross((address,uint256))231 function removeCollectionAdminCross(EthCrossAccount memory admin) external;232233 // /// Add collection admin.234 // /// @param newAdmin Address of the added administrator.235 // /// @dev EVM selector for this function is: 0x92e462c7,236 // /// or in textual repr: addCollectionAdmin(address)237 // function addCollectionAdmin(address newAdmin) external;238239 // /// Remove collection admin.240 // ///241 // /// @param admin Address of the removed administrator.242 // /// @dev EVM selector for this function is: 0xfafd7b42,243 // /// or in textual repr: removeCollectionAdmin(address)244 // function removeCollectionAdmin(address admin) external;245246 /// Toggle accessibility of collection nesting.247 ///248 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'249 /// @dev EVM selector for this function is: 0x112d4586,250 /// or in textual repr: setCollectionNesting(bool)251 function setCollectionNesting(bool enable) external;252253 /// Toggle accessibility of collection nesting.254 ///255 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'256 /// @param collections Addresses of collections that will be available for nesting.257 /// @dev EVM selector for this function is: 0x64872396,258 /// or in textual repr: setCollectionNesting(bool,address[])259 function setCollectionNesting(bool enable, address[] memory collections) external;260261 /// Returns nesting for a collection262 /// @dev EVM selector for this function is: 0x22d25bfe,263 /// or in textual repr: collectionNestingRestrictedCollectionIds()264 function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);265266 /// Returns permissions for a collection267 /// @dev EVM selector for this function is: 0x5b2eaf4b,268 /// or in textual repr: collectionNestingPermissions()269 function collectionNestingPermissions() external view returns (Tuple33[] memory);270271 /// Set the collection access method.272 /// @param mode Access mode273 /// 0 for Normal274 /// 1 for AllowList275 /// @dev EVM selector for this function is: 0x41835d4c,276 /// or in textual repr: setCollectionAccess(uint8)277 function setCollectionAccess(uint8 mode) external;278279 /// Checks that user allowed to operate with collection.280 ///281 /// @param user User address to check.282 /// @dev EVM selector for this function is: 0x91b6df49,283 /// or in textual repr: allowlistedCross((address,uint256))284 function allowlistedCross(EthCrossAccount memory user) external view returns (bool);285286 // /// Add the user to the allowed list.287 // ///288 // /// @param user Address of a trusted user.289 // /// @dev EVM selector for this function is: 0x67844fe6,290 // /// or in textual repr: addToCollectionAllowList(address)291 // function addToCollectionAllowList(address user) external;292293 /// Add user to allowed list.294 ///295 /// @param user User cross account address.296 /// @dev EVM selector for this function is: 0xa0184a3a,297 /// or in textual repr: addToCollectionAllowListCross((address,uint256))298 function addToCollectionAllowListCross(EthCrossAccount memory user) external;299300 // /// Remove the user from the allowed list.301 // ///302 // /// @param user Address of a removed user.303 // /// @dev EVM selector for this function is: 0x85c51acb,304 // /// or in textual repr: removeFromCollectionAllowList(address)305 // function removeFromCollectionAllowList(address user) external;306307 /// Remove user from allowed list.308 ///309 /// @param user User cross account address.310 /// @dev EVM selector for this function is: 0x09ba452a,311 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))312 function removeFromCollectionAllowListCross(EthCrossAccount memory user) external;313314 /// Switch permission for minting.315 ///316 /// @param mode Enable if "true".317 /// @dev EVM selector for this function is: 0x00018e84,318 /// or in textual repr: setCollectionMintMode(bool)319 function setCollectionMintMode(bool mode) external;320321 // /// Check that account is the owner or admin of the collection322 // ///323 // /// @param user account to verify324 // /// @return "true" if account is the owner or admin325 // /// @dev EVM selector for this function is: 0x9811b0c7,326 // /// or in textual repr: isOwnerOrAdmin(address)327 // function isOwnerOrAdmin(address user) external view returns (bool);328329 /// Check that account is the owner or admin of the collection330 ///331 /// @param user User cross account to verify332 /// @return "true" if account is the owner or admin333 /// @dev EVM selector for this function is: 0x3e75a905,334 /// or in textual repr: isOwnerOrAdminCross((address,uint256))335 function isOwnerOrAdminCross(EthCrossAccount memory user) external view returns (bool);336337 /// Returns collection type338 ///339 /// @return `Fungible` or `NFT` or `ReFungible`340 /// @dev EVM selector for this function is: 0xd34b55b8,341 /// or in textual repr: uniqueCollectionType()342 function uniqueCollectionType() external view returns (string memory);343344 /// Get collection owner.345 ///346 /// @return Tuble with sponsor address and his substrate mirror.347 /// If address is canonical then substrate mirror is zero and vice versa.348 /// @dev EVM selector for this function is: 0xdf727d3b,349 /// or in textual repr: collectionOwner()350 function collectionOwner() external view returns (EthCrossAccount memory);351352 // /// Changes collection owner to another account353 // ///354 // /// @dev Owner can be changed only by current owner355 // /// @param newOwner new owner account356 // /// @dev EVM selector for this function is: 0x4f53e226,357 // /// or in textual repr: changeCollectionOwner(address)358 // function changeCollectionOwner(address newOwner) external;359360 /// Get collection administrators361 ///362 /// @return Vector of tuples with admins address and his substrate mirror.363 /// If address is canonical then substrate mirror is zero and vice versa.364 /// @dev EVM selector for this function is: 0x5813216b,365 /// or in textual repr: collectionAdmins()366 function collectionAdmins() external view returns (EthCrossAccount[] memory);367368 /// Changes collection owner to another account369 ///370 /// @dev Owner can be changed only by current owner371 /// @param newOwner new owner cross account372 /// @dev EVM selector for this function is: 0x6496c497,373 /// or in textual repr: changeCollectionOwnerCross((address,uint256))374 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) external;375}376377/// @dev Cross account struct378struct EthCrossAccount {379 address eth;380 uint256 sub;381}382383/// @dev anonymous struct384struct Tuple33 {385 CollectionPermissions field_0;386 bool field_1;387}388389enum CollectionPermissions {390 CollectionAdmin,391 TokenOwner392}393394/// @dev anonymous struct395struct Tuple30 {396 bool field_0;397 uint256[] field_1;398}399400/// @dev anonymous struct401struct Tuple26 {402 address field_0;403 uint256 field_1;404}405406/// @dev the ERC-165 identifier for this interface is 0x5b5e139f407interface ERC721Metadata is Dummy, ERC165 {408 // /// @notice A descriptive name for a collection of NFTs in this contract409 // /// @dev real implementation of this function lies in `ERC721UniqueExtensions`410 // /// @dev EVM selector for this function is: 0x06fdde03,411 // /// or in textual repr: name()412 // function name() external view returns (string memory);413414 // /// @notice An abbreviated name for NFTs in this contract415 // /// @dev real implementation of this function lies in `ERC721UniqueExtensions`416 // /// @dev EVM selector for this function is: 0x95d89b41,417 // /// or in textual repr: symbol()418 // function symbol() external view returns (string memory);419420 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.421 ///422 /// @dev If the token has a `url` property and it is not empty, it is returned.423 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.424 /// If the collection property `baseURI` is empty or absent, return "" (empty string)425 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix426 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).427 ///428 /// @return token's const_metadata429 /// @dev EVM selector for this function is: 0xc87b56dd,430 /// or in textual repr: tokenURI(uint256)431 function tokenURI(uint256 tokenId) external view returns (string memory);432}433434/// @title ERC721 Token that can be irreversibly burned (destroyed).435/// @dev the ERC-165 identifier for this interface is 0x42966c68436interface ERC721Burnable is Dummy, ERC165 {437 /// @notice Burns a specific ERC721 token.438 /// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized439 /// operator of the current owner.440 /// @param tokenId The RFT to approve441 /// @dev EVM selector for this function is: 0x42966c68,442 /// or in textual repr: burn(uint256)443 function burn(uint256 tokenId) external;444}445446/// @dev inlined interface447interface ERC721UniqueMintableEvents {448 event MintingFinished();449}450451/// @title ERC721 minting logic.452/// @dev the ERC-165 identifier for this interface is 0x476ff149453interface ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents {454 /// @dev EVM selector for this function is: 0x05d2035b,455 /// or in textual repr: mintingFinished()456 function mintingFinished() external view returns (bool);457458 /// @notice Function to mint token.459 /// @param to The new owner460 /// @return uint256 The id of the newly minted token461 /// @dev EVM selector for this function is: 0x6a627842,462 /// or in textual repr: mint(address)463 function mint(address to) external returns (uint256);464465 // /// @notice Function to mint token.466 // /// @dev `tokenId` should be obtained with `nextTokenId` method,467 // /// unlike standard, you can't specify it manually468 // /// @param to The new owner469 // /// @param tokenId ID of the minted RFT470 // /// @dev EVM selector for this function is: 0x40c10f19,471 // /// or in textual repr: mint(address,uint256)472 // function mint(address to, uint256 tokenId) external returns (bool);473474 /// @notice Function to mint token with the given tokenUri.475 /// @param to The new owner476 /// @param tokenUri Token URI that would be stored in the NFT properties477 /// @return uint256 The id of the newly minted token478 /// @dev EVM selector for this function is: 0x45c17782,479 /// or in textual repr: mintWithTokenURI(address,string)480 function mintWithTokenURI(address to, string memory tokenUri) external returns (uint256);481482 // /// @notice Function to mint token with the given tokenUri.483 // /// @dev `tokenId` should be obtained with `nextTokenId` method,484 // /// unlike standard, you can't specify it manually485 // /// @param to The new owner486 // /// @param tokenId ID of the minted RFT487 // /// @param tokenUri Token URI that would be stored in the RFT properties488 // /// @dev EVM selector for this function is: 0x50bb4e7f,489 // /// or in textual repr: mintWithTokenURI(address,uint256,string)490 // function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) external returns (bool);491492 /// @dev Not implemented493 /// @dev EVM selector for this function is: 0x7d64bcb4,494 /// or in textual repr: finishMinting()495 function finishMinting() external returns (bool);496}497498/// @title Unique extensions for ERC721.499/// @dev the ERC-165 identifier for this interface is 0x12f7d6c1500interface ERC721UniqueExtensions is Dummy, ERC165 {501 /// @notice A descriptive name for a collection of NFTs in this contract502 /// @dev EVM selector for this function is: 0x06fdde03,503 /// or in textual repr: name()504 function name() external view returns (string memory);505506 /// @notice An abbreviated name for NFTs in this contract507 /// @dev EVM selector for this function is: 0x95d89b41,508 /// or in textual repr: symbol()509 function symbol() external view returns (string memory);510511 /// @notice A description for the collection.512 /// @dev EVM selector for this function is: 0x7284e416,513 /// or in textual repr: description()514 function description() external view returns (string memory);515516 /// Returns the owner (in cross format) of the token.517 ///518 /// @param tokenId Id for the token.519 /// @dev EVM selector for this function is: 0x2b29dace,520 /// or in textual repr: crossOwnerOf(uint256)521 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);522523 /// Returns the token properties.524 ///525 /// @param tokenId Id for the token.526 /// @param keys Properties keys. Empty keys for all propertyes.527 /// @return Vector of properties key/value pairs.528 /// @dev EVM selector for this function is: 0xe07ede7e,529 /// or in textual repr: properties(uint256,string[])530 function properties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory);531532 /// @notice Transfer ownership of an RFT533 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`534 /// is the zero address. Throws if `tokenId` is not a valid RFT.535 /// Throws if RFT pieces have multiple owners.536 /// @param to The new owner537 /// @param tokenId The RFT to transfer538 /// @dev EVM selector for this function is: 0xa9059cbb,539 /// or in textual repr: transfer(address,uint256)540 function transfer(address to, uint256 tokenId) external;541542 /// @notice Transfer ownership of an RFT543 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`544 /// is the zero address. Throws if `tokenId` is not a valid RFT.545 /// Throws if RFT pieces have multiple owners.546 /// @param to The new owner547 /// @param tokenId The RFT to transfer548 /// @dev EVM selector for this function is: 0x2ada85ff,549 /// or in textual repr: transferCross((address,uint256),uint256)550 function transferCross(EthCrossAccount memory to, uint256 tokenId) external;551552 /// @notice Transfer ownership of an RFT553 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`554 /// is the zero address. Throws if `tokenId` is not a valid RFT.555 /// Throws if RFT pieces have multiple owners.556 /// @param to The new owner557 /// @param tokenId The RFT to transfer558 /// @dev EVM selector for this function is: 0xd5cf430b,559 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)560 function transferFromCross(561 EthCrossAccount memory from,562 EthCrossAccount memory to,563 uint256 tokenId564 ) external;565566 // /// @notice Burns a specific ERC721 token.567 // /// @dev Throws unless `msg.sender` is the current owner or an authorized568 // /// operator for this RFT. Throws if `from` is not the current owner. Throws569 // /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.570 // /// Throws if RFT pieces have multiple owners.571 // /// @param from The current owner of the RFT572 // /// @param tokenId The RFT to transfer573 // /// @dev EVM selector for this function is: 0x79cc6790,574 // /// or in textual repr: burnFrom(address,uint256)575 // function burnFrom(address from, uint256 tokenId) external;576577 /// @notice Burns a specific ERC721 token.578 /// @dev Throws unless `msg.sender` is the current owner or an authorized579 /// operator for this RFT. Throws if `from` is not the current owner. Throws580 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.581 /// Throws if RFT pieces have multiple owners.582 /// @param from The current owner of the RFT583 /// @param tokenId The RFT to transfer584 /// @dev EVM selector for this function is: 0xbb2f5a58,585 /// or in textual repr: burnFromCross((address,uint256),uint256)586 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) external;587588 /// @notice Returns next free RFT ID.589 /// @dev EVM selector for this function is: 0x75794a3c,590 /// or in textual repr: nextTokenId()591 function nextTokenId() external view returns (uint256);592593 // /// @notice Function to mint multiple tokens.594 // /// @dev `tokenIds` should be an array of consecutive numbers and first number595 // /// should be obtained with `nextTokenId` method596 // /// @param to The new owner597 // /// @param tokenIds IDs of the minted RFTs598 // /// @dev EVM selector for this function is: 0x44a9945e,599 // /// or in textual repr: mintBulk(address,uint256[])600 // function mintBulk(address to, uint256[] memory tokenIds) external returns (bool);601602 // /// @notice Function to mint multiple tokens with the given tokenUris.603 // /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive604 // /// numbers and first number should be obtained with `nextTokenId` method605 // /// @param to The new owner606 // /// @param tokens array of pairs of token ID and token URI for minted tokens607 // /// @dev EVM selector for this function is: 0x36543006,608 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])609 // function mintBulkWithTokenURI(address to, Tuple12[] memory tokens) external returns (bool);610611 /// Returns EVM address for refungible token612 ///613 /// @param token ID of the token614 /// @dev EVM selector for this function is: 0xab76fac6,615 /// or in textual repr: tokenContractAddress(uint256)616 function tokenContractAddress(uint256 token) external view returns (address);617}618619/// @dev anonymous struct620struct Tuple12 {621 uint256 field_0;622 string field_1;623}624625/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension626/// @dev See https://eips.ethereum.org/EIPS/eip-721627/// @dev the ERC-165 identifier for this interface is 0x780e9d63628interface ERC721Enumerable is Dummy, ERC165 {629 /// @notice Enumerate valid RFTs630 /// @param index A counter less than `totalSupply()`631 /// @return The token identifier for the `index`th NFT,632 /// (sort order not specified)633 /// @dev EVM selector for this function is: 0x4f6ccce7,634 /// or in textual repr: tokenByIndex(uint256)635 function tokenByIndex(uint256 index) external view returns (uint256);636637 /// Not implemented638 /// @dev EVM selector for this function is: 0x2f745c59,639 /// or in textual repr: tokenOfOwnerByIndex(address,uint256)640 function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);641642 /// @notice Count RFTs tracked by this contract643 /// @return A count of valid RFTs tracked by this contract, where each one of644 /// them has an assigned and queryable owner not equal to the zero address645 /// @dev EVM selector for this function is: 0x18160ddd,646 /// or in textual repr: totalSupply()647 function totalSupply() external view returns (uint256);648}649650/// @dev inlined interface651interface ERC721Events {652 event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);653 event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);654 event ApprovalForAll(address indexed owner, address indexed operator, bool approved);655}656657/// @title ERC-721 Non-Fungible Token Standard658/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md659/// @dev the ERC-165 identifier for this interface is 0x4016cd87660interface ERC721 is Dummy, ERC165, ERC721Events {661 /// @notice Count all RFTs assigned to an owner662 /// @dev RFTs assigned to the zero address are considered invalid, and this663 /// function throws for queries about the zero address.664 /// @param owner An address for whom to query the balance665 /// @return The number of RFTs owned by `owner`, possibly zero666 /// @dev EVM selector for this function is: 0x70a08231,667 /// or in textual repr: balanceOf(address)668 function balanceOf(address owner) external view returns (uint256);669670 /// @notice Find the owner of an RFT671 /// @dev RFTs assigned to zero address are considered invalid, and queries672 /// about them do throw.673 /// Returns special 0xffffffffffffffffffffffffffffffffffffffff address for674 /// the tokens that are partially owned.675 /// @param tokenId The identifier for an RFT676 /// @return The address of the owner of the RFT677 /// @dev EVM selector for this function is: 0x6352211e,678 /// or in textual repr: ownerOf(uint256)679 function ownerOf(uint256 tokenId) external view returns (address);680681 /// @dev Not implemented682 /// @dev EVM selector for this function is: 0x60a11672,683 /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)684 function safeTransferFromWithData(685 address from,686 address to,687 uint256 tokenId,688 bytes memory data689 ) external;690691 /// @dev Not implemented692 /// @dev EVM selector for this function is: 0x42842e0e,693 /// or in textual repr: safeTransferFrom(address,address,uint256)694 function safeTransferFrom(695 address from,696 address to,697 uint256 tokenId698 ) external;699700 /// @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE701 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE702 /// THEY MAY BE PERMANENTLY LOST703 /// @dev Throws unless `msg.sender` is the current owner or an authorized704 /// operator for this RFT. Throws if `from` is not the current owner. Throws705 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.706 /// Throws if RFT pieces have multiple owners.707 /// @param from The current owner of the NFT708 /// @param to The new owner709 /// @param tokenId The NFT to transfer710 /// @dev EVM selector for this function is: 0x23b872dd,711 /// or in textual repr: transferFrom(address,address,uint256)712 function transferFrom(713 address from,714 address to,715 uint256 tokenId716 ) external;717718 /// @dev Not implemented719 /// @dev EVM selector for this function is: 0x095ea7b3,720 /// or in textual repr: approve(address,uint256)721 function approve(address approved, uint256 tokenId) external;722723 /// @notice Sets or unsets the approval of a given operator.724 /// The `operator` is allowed to transfer all token pieces of the `caller` on their behalf.725 /// @param operator Operator726 /// @param approved Should operator status be granted or revoked?727 /// @dev EVM selector for this function is: 0xa22cb465,728 /// or in textual repr: setApprovalForAll(address,bool)729 function setApprovalForAll(address operator, bool approved) external;730731 /// @dev Not implemented732 /// @dev EVM selector for this function is: 0x081812fc,733 /// or in textual repr: getApproved(uint256)734 function getApproved(uint256 tokenId) external view returns (address);735736 /// @notice Tells whether the given `owner` approves the `operator`.737 /// @dev EVM selector for this function is: 0xe985e9c5,738 /// or in textual repr: isApprovedForAll(address,address)739 function isApprovedForAll(address owner, address operator) external view returns (bool);740741 /// @notice Returns collection helper contract address742 /// @dev EVM selector for this function is: 0x1896cce6,743 /// or in textual repr: collectionHelperAddress()744 function collectionHelperAddress() external view returns (address);745}746747interface UniqueRefungible is748 Dummy,749 ERC165,750 ERC721,751 ERC721Enumerable,752 ERC721UniqueExtensions,753 ERC721UniqueMintable,754 ERC721Burnable,755 ERC721Metadata,756 Collection,757 TokenProperties758{}1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56/// @dev common stubs holder7interface Dummy {89}1011interface ERC165 is Dummy {12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}1415/// @title A contract that allows to set and delete token properties and change token property permissions.16/// @dev the ERC-165 identifier for this interface is 0xde0695c217interface TokenProperties is Dummy, ERC165 {18 // /// @notice Set permissions for token property.19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.20 // /// @param key Property key.21 // /// @param isMutable Permission to mutate property.22 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.23 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.24 // /// @dev EVM selector for this function is: 0x222d97fa,25 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)26 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) external;2728 /// @notice Set permissions for token property.29 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.30 /// @param permissions Permissions for keys.31 /// @dev EVM selector for this function is: 0xbd92983a,32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])33 function setTokenPropertyPermissions(Tuple47[] memory permissions) external;3435 /// @notice Get permissions for token properties.36 /// @dev EVM selector for this function is: 0xf23d7790,37 /// or in textual repr: tokenPropertyPermissions()38 function tokenPropertyPermissions() external view returns (Tuple47[] memory);3940 // /// @notice Set token property value.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.42 // /// @param tokenId ID of the token.43 // /// @param key Property key.44 // /// @param value Property value.45 // /// @dev EVM selector for this function is: 0x1752d67b,46 // /// or in textual repr: setProperty(uint256,string,bytes)47 // function setProperty(uint256 tokenId, string memory key, bytes memory value) external;4849 /// @notice Set token properties value.50 /// @dev Throws error if `msg.sender` has no permission to edit the property.51 /// @param tokenId ID of the token.52 /// @param properties settable properties53 /// @dev EVM selector for this function is: 0x14ed3a6e,54 /// or in textual repr: setProperties(uint256,(string,bytes)[])55 function setProperties(uint256 tokenId, Property[] memory properties) external;5657 // /// @notice Delete token property value.58 // /// @dev Throws error if `msg.sender` has no permission to edit the property.59 // /// @param tokenId ID of the token.60 // /// @param key Property key.61 // /// @dev EVM selector for this function is: 0x066111d1,62 // /// or in textual repr: deleteProperty(uint256,string)63 // function deleteProperty(uint256 tokenId, string memory key) external;6465 /// @notice Delete token properties value.66 /// @dev Throws error if `msg.sender` has no permission to edit the property.67 /// @param tokenId ID of the token.68 /// @param keys Properties key.69 /// @dev EVM selector for this function is: 0xc472d371,70 /// or in textual repr: deleteProperties(uint256,string[])71 function deleteProperties(uint256 tokenId, string[] memory keys) external;7273 /// @notice Get token property value.74 /// @dev Throws error if key not found75 /// @param tokenId ID of the token.76 /// @param key Property key.77 /// @return Property value bytes78 /// @dev EVM selector for this function is: 0x7228c327,79 /// or in textual repr: property(uint256,string)80 function property(uint256 tokenId, string memory key) external view returns (bytes memory);81}8283/// @dev Property struct84struct Property {85 string key;86 bytes value;87}8889enum EthTokenPermissions {90 Mutable,91 TokenOwner,92 CollectionAdmin93}9495/// @dev anonymous struct96struct Tuple47 {97 string field_0;98 Tuple45[] field_1;99}100101/// @dev anonymous struct102struct Tuple45 {103 EthTokenPermissions field_0;104 bool field_1;105}106107/// @title A contract that allows you to work with collections.108<<<<<<< HEAD109/// @dev the ERC-165 identifier for this interface is 0xb5e1747f110=======111/// @dev the ERC-165 identifier for this interface is 0xf8ebdec0112>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`113interface Collection is Dummy, ERC165 {114 // /// Set collection property.115 // ///116 // /// @param key Property key.117 // /// @param value Propery value.118 // /// @dev EVM selector for this function is: 0x2f073f66,119 // /// or in textual repr: setCollectionProperty(string,bytes)120 // function setCollectionProperty(string memory key, bytes memory value) external;121122 /// Set collection properties.123 ///124 /// @param properties Vector of properties key/value pair.125 /// @dev EVM selector for this function is: 0x50b26b2a,126 /// or in textual repr: setCollectionProperties((string,bytes)[])127 function setCollectionProperties(Property[] memory properties) external;128129 // /// Delete collection property.130 // ///131 // /// @param key Property key.132 // /// @dev EVM selector for this function is: 0x7b7debce,133 // /// or in textual repr: deleteCollectionProperty(string)134 // function deleteCollectionProperty(string memory key) external;135136 /// Delete collection properties.137 ///138 /// @param keys Properties keys.139 /// @dev EVM selector for this function is: 0xee206ee3,140 /// or in textual repr: deleteCollectionProperties(string[])141 function deleteCollectionProperties(string[] memory keys) external;142143 /// Get collection property.144 ///145 /// @dev Throws error if key not found.146 ///147 /// @param key Property key.148 /// @return bytes The property corresponding to the key.149 /// @dev EVM selector for this function is: 0xcf24fd6d,150 /// or in textual repr: collectionProperty(string)151 function collectionProperty(string memory key) external view returns (bytes memory);152153 /// Get collection properties.154 ///155 /// @param keys Properties keys. Empty keys for all propertyes.156 /// @return Vector of properties key/value pairs.157 /// @dev EVM selector for this function is: 0x285fb8e6,158 /// or in textual repr: collectionProperties(string[])159 function collectionProperties(string[] memory keys) external view returns (Property[] memory);160161 // /// Set the sponsor of the collection.162 // ///163 // /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.164 // ///165 // /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.166 // /// @dev EVM selector for this function is: 0x7623402e,167 // /// or in textual repr: setCollectionSponsor(address)168 // function setCollectionSponsor(address sponsor) external;169170 /// Set the sponsor of the collection.171 ///172 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.173 ///174 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.175 /// @dev EVM selector for this function is: 0x84a1d5a8,176 /// or in textual repr: setCollectionSponsorCross((address,uint256))177 function setCollectionSponsorCross(EthCrossAccount memory sponsor) external;178179 /// Whether there is a pending sponsor.180 /// @dev EVM selector for this function is: 0x058ac185,181 /// or in textual repr: hasCollectionPendingSponsor()182 function hasCollectionPendingSponsor() external view returns (bool);183184 /// Collection sponsorship confirmation.185 ///186 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.187 /// @dev EVM selector for this function is: 0x3c50e97a,188 /// or in textual repr: confirmCollectionSponsorship()189 function confirmCollectionSponsorship() external;190191 /// Remove collection sponsor.192 /// @dev EVM selector for this function is: 0x6e0326a3,193 /// or in textual repr: removeCollectionSponsor()194 function removeCollectionSponsor() external;195196 /// Get current sponsor.197 ///198 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.199 /// @dev EVM selector for this function is: 0x6ec0a9f1,200 /// or in textual repr: collectionSponsor()201 function collectionSponsor() external view returns (Tuple26 memory);202203 /// Get current collection limits.204 ///205 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:206 /// "accountTokenOwnershipLimit",207 /// "sponsoredDataSize",208 /// "sponsoredDataRateLimit",209 /// "tokenLimit",210 /// "sponsorTransferTimeout",211 /// "sponsorApproveTimeout"212 /// "ownerCanTransfer",213 /// "ownerCanDestroy",214 /// "transfersEnabled"215 /// Return `false` if a limit not set.216 /// @dev EVM selector for this function is: 0xf63bc572,217 /// or in textual repr: collectionLimits()218 function collectionLimits() external view returns (Tuple29[] memory);219220 /// Set limits for the collection.221 /// @dev Throws error if limit not found.222 /// @param limit Name of the limit. Valid names:223 /// "accountTokenOwnershipLimit",224 /// "sponsoredDataSize",225 /// "sponsoredDataRateLimit",226 /// "tokenLimit",227 /// "sponsorTransferTimeout",228 /// "sponsorApproveTimeout"229 /// "ownerCanTransfer",230 /// "ownerCanDestroy",231 /// "transfersEnabled"232 /// @param value Value of the limit.233 /// @dev EVM selector for this function is: 0x88150bd0,234 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)235 function setCollectionLimit(236 CollectionLimits limit,237 bool status,238 uint256 value239 ) external;240241 /// Get contract address.242 /// @dev EVM selector for this function is: 0xf6b4dfb4,243 /// or in textual repr: contractAddress()244 function contractAddress() external view returns (address);245246 /// Add collection admin.247 /// @param newAdmin Cross account administrator address.248 /// @dev EVM selector for this function is: 0x859aa7d6,249 /// or in textual repr: addCollectionAdminCross((address,uint256))250 function addCollectionAdminCross(EthCrossAccount memory newAdmin) external;251252 /// Remove collection admin.253 /// @param admin Cross account administrator address.254 /// @dev EVM selector for this function is: 0x6c0cd173,255 /// or in textual repr: removeCollectionAdminCross((address,uint256))256 function removeCollectionAdminCross(EthCrossAccount memory admin) external;257258 // /// Add collection admin.259 // /// @param newAdmin Address of the added administrator.260 // /// @dev EVM selector for this function is: 0x92e462c7,261 // /// or in textual repr: addCollectionAdmin(address)262 // function addCollectionAdmin(address newAdmin) external;263264 // /// Remove collection admin.265 // ///266 // /// @param admin Address of the removed administrator.267 // /// @dev EVM selector for this function is: 0xfafd7b42,268 // /// or in textual repr: removeCollectionAdmin(address)269 // function removeCollectionAdmin(address admin) external;270271 /// Toggle accessibility of collection nesting.272 ///273 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'274 /// @dev EVM selector for this function is: 0x112d4586,275 /// or in textual repr: setCollectionNesting(bool)276 function setCollectionNesting(bool enable) external;277278 /// Toggle accessibility of collection nesting.279 ///280 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'281 /// @param collections Addresses of collections that will be available for nesting.282 /// @dev EVM selector for this function is: 0x64872396,283 /// or in textual repr: setCollectionNesting(bool,address[])284 function setCollectionNesting(bool enable, address[] memory collections) external;285286 /// Returns nesting for a collection287 /// @dev EVM selector for this function is: 0x22d25bfe,288 /// or in textual repr: collectionNestingRestrictedCollectionIds()289 function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);290291 /// Returns permissions for a collection292 /// @dev EVM selector for this function is: 0x5b2eaf4b,293 /// or in textual repr: collectionNestingPermissions()294 function collectionNestingPermissions() external view returns (Tuple33[] memory);295296 /// Set the collection access method.297 /// @param mode Access mode298 /// 0 for Normal299 /// 1 for AllowList300 /// @dev EVM selector for this function is: 0x41835d4c,301 /// or in textual repr: setCollectionAccess(uint8)302 function setCollectionAccess(uint8 mode) external;303304 /// Checks that user allowed to operate with collection.305 ///306 /// @param user User address to check.307 /// @dev EVM selector for this function is: 0x91b6df49,308 /// or in textual repr: allowlistedCross((address,uint256))309 function allowlistedCross(EthCrossAccount memory user) external view returns (bool);310311 // /// Add the user to the allowed list.312 // ///313 // /// @param user Address of a trusted user.314 // /// @dev EVM selector for this function is: 0x67844fe6,315 // /// or in textual repr: addToCollectionAllowList(address)316 // function addToCollectionAllowList(address user) external;317318 /// Add user to allowed list.319 ///320 /// @param user User cross account address.321 /// @dev EVM selector for this function is: 0xa0184a3a,322 /// or in textual repr: addToCollectionAllowListCross((address,uint256))323 function addToCollectionAllowListCross(EthCrossAccount memory user) external;324325 // /// Remove the user from the allowed list.326 // ///327 // /// @param user Address of a removed user.328 // /// @dev EVM selector for this function is: 0x85c51acb,329 // /// or in textual repr: removeFromCollectionAllowList(address)330 // function removeFromCollectionAllowList(address user) external;331332 /// Remove user from allowed list.333 ///334 /// @param user User cross account address.335 /// @dev EVM selector for this function is: 0x09ba452a,336 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))337 function removeFromCollectionAllowListCross(EthCrossAccount memory user) external;338339 /// Switch permission for minting.340 ///341 /// @param mode Enable if "true".342 /// @dev EVM selector for this function is: 0x00018e84,343 /// or in textual repr: setCollectionMintMode(bool)344 function setCollectionMintMode(bool mode) external;345346 // /// Check that account is the owner or admin of the collection347 // ///348 // /// @param user account to verify349 // /// @return "true" if account is the owner or admin350 // /// @dev EVM selector for this function is: 0x9811b0c7,351 // /// or in textual repr: isOwnerOrAdmin(address)352 // function isOwnerOrAdmin(address user) external view returns (bool);353354 /// Check that account is the owner or admin of the collection355 ///356 /// @param user User cross account to verify357 /// @return "true" if account is the owner or admin358 /// @dev EVM selector for this function is: 0x3e75a905,359 /// or in textual repr: isOwnerOrAdminCross((address,uint256))360 function isOwnerOrAdminCross(EthCrossAccount memory user) external view returns (bool);361362 /// Returns collection type363 ///364 /// @return `Fungible` or `NFT` or `ReFungible`365 /// @dev EVM selector for this function is: 0xd34b55b8,366 /// or in textual repr: uniqueCollectionType()367 function uniqueCollectionType() external view returns (string memory);368369 /// Get collection owner.370 ///371 /// @return Tuble with sponsor address and his substrate mirror.372 /// If address is canonical then substrate mirror is zero and vice versa.373 /// @dev EVM selector for this function is: 0xdf727d3b,374 /// or in textual repr: collectionOwner()375 function collectionOwner() external view returns (EthCrossAccount memory);376377 // /// Changes collection owner to another account378 // ///379 // /// @dev Owner can be changed only by current owner380 // /// @param newOwner new owner account381 // /// @dev EVM selector for this function is: 0x4f53e226,382 // /// or in textual repr: changeCollectionOwner(address)383 // function changeCollectionOwner(address newOwner) external;384385 /// Get collection administrators386 ///387 /// @return Vector of tuples with admins address and his substrate mirror.388 /// If address is canonical then substrate mirror is zero and vice versa.389 /// @dev EVM selector for this function is: 0x5813216b,390 /// or in textual repr: collectionAdmins()391 function collectionAdmins() external view returns (EthCrossAccount[] memory);392393 /// Changes collection owner to another account394 ///395 /// @dev Owner can be changed only by current owner396 /// @param newOwner new owner cross account397 /// @dev EVM selector for this function is: 0x6496c497,398 /// or in textual repr: changeCollectionOwnerCross((address,uint256))399 function changeCollectionOwnerCross(EthCrossAccount memory newOwner) external;400}401402/// @dev Cross account struct403struct EthCrossAccount {404 address eth;405 uint256 sub;406}407408enum CollectionLimits {409 AccountTokenOwnership,410 SponsoredDataSize,411 SponsoredDataRateLimit,412 TokenLimit,413 SponsorTransferTimeout,414 SponsorApproveTimeout,415 OwnerCanTransfer,416 OwnerCanDestroy,417 TransferEnabled418}419420/// @dev anonymous struct421struct Tuple29 {422 CollectionLimits field_0;423 bool field_1;424 uint256 field_2;425}426427/// @dev anonymous struct428struct Tuple33 {429 CollectionPermissions field_0;430 bool field_1;431}432433enum CollectionPermissions {434 CollectionAdmin,435 TokenOwner436}437438/// @dev anonymous struct439struct Tuple30 {440 bool field_0;441 uint256[] field_1;442}443444/// @dev anonymous struct445struct Tuple26 {446 address field_0;447 uint256 field_1;448}449450/// @dev the ERC-165 identifier for this interface is 0x5b5e139f451interface ERC721Metadata is Dummy, ERC165 {452 // /// @notice A descriptive name for a collection of NFTs in this contract453 // /// @dev real implementation of this function lies in `ERC721UniqueExtensions`454 // /// @dev EVM selector for this function is: 0x06fdde03,455 // /// or in textual repr: name()456 // function name() external view returns (string memory);457458 // /// @notice An abbreviated name for NFTs in this contract459 // /// @dev real implementation of this function lies in `ERC721UniqueExtensions`460 // /// @dev EVM selector for this function is: 0x95d89b41,461 // /// or in textual repr: symbol()462 // function symbol() external view returns (string memory);463464 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.465 ///466 /// @dev If the token has a `url` property and it is not empty, it is returned.467 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.468 /// If the collection property `baseURI` is empty or absent, return "" (empty string)469 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix470 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).471 ///472 /// @return token's const_metadata473 /// @dev EVM selector for this function is: 0xc87b56dd,474 /// or in textual repr: tokenURI(uint256)475 function tokenURI(uint256 tokenId) external view returns (string memory);476}477478/// @title ERC721 Token that can be irreversibly burned (destroyed).479/// @dev the ERC-165 identifier for this interface is 0x42966c68480interface ERC721Burnable is Dummy, ERC165 {481 /// @notice Burns a specific ERC721 token.482 /// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized483 /// operator of the current owner.484 /// @param tokenId The RFT to approve485 /// @dev EVM selector for this function is: 0x42966c68,486 /// or in textual repr: burn(uint256)487 function burn(uint256 tokenId) external;488}489490/// @dev inlined interface491interface ERC721UniqueMintableEvents {492 event MintingFinished();493}494495/// @title ERC721 minting logic.496/// @dev the ERC-165 identifier for this interface is 0x476ff149497interface ERC721UniqueMintable is Dummy, ERC165, ERC721UniqueMintableEvents {498 /// @dev EVM selector for this function is: 0x05d2035b,499 /// or in textual repr: mintingFinished()500 function mintingFinished() external view returns (bool);501502 /// @notice Function to mint token.503 /// @param to The new owner504 /// @return uint256 The id of the newly minted token505 /// @dev EVM selector for this function is: 0x6a627842,506 /// or in textual repr: mint(address)507 function mint(address to) external returns (uint256);508509 // /// @notice Function to mint token.510 // /// @dev `tokenId` should be obtained with `nextTokenId` method,511 // /// unlike standard, you can't specify it manually512 // /// @param to The new owner513 // /// @param tokenId ID of the minted RFT514 // /// @dev EVM selector for this function is: 0x40c10f19,515 // /// or in textual repr: mint(address,uint256)516 // function mint(address to, uint256 tokenId) external returns (bool);517518 /// @notice Function to mint token with the given tokenUri.519 /// @param to The new owner520 /// @param tokenUri Token URI that would be stored in the NFT properties521 /// @return uint256 The id of the newly minted token522 /// @dev EVM selector for this function is: 0x45c17782,523 /// or in textual repr: mintWithTokenURI(address,string)524 function mintWithTokenURI(address to, string memory tokenUri) external returns (uint256);525526 // /// @notice Function to mint token with the given tokenUri.527 // /// @dev `tokenId` should be obtained with `nextTokenId` method,528 // /// unlike standard, you can't specify it manually529 // /// @param to The new owner530 // /// @param tokenId ID of the minted RFT531 // /// @param tokenUri Token URI that would be stored in the RFT properties532 // /// @dev EVM selector for this function is: 0x50bb4e7f,533 // /// or in textual repr: mintWithTokenURI(address,uint256,string)534 // function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) external returns (bool);535536 /// @dev Not implemented537 /// @dev EVM selector for this function is: 0x7d64bcb4,538 /// or in textual repr: finishMinting()539 function finishMinting() external returns (bool);540}541542/// @title Unique extensions for ERC721.543/// @dev the ERC-165 identifier for this interface is 0x12f7d6c1544interface ERC721UniqueExtensions is Dummy, ERC165 {545 /// @notice A descriptive name for a collection of NFTs in this contract546 /// @dev EVM selector for this function is: 0x06fdde03,547 /// or in textual repr: name()548 function name() external view returns (string memory);549550 /// @notice An abbreviated name for NFTs in this contract551 /// @dev EVM selector for this function is: 0x95d89b41,552 /// or in textual repr: symbol()553 function symbol() external view returns (string memory);554555 /// @notice A description for the collection.556 /// @dev EVM selector for this function is: 0x7284e416,557 /// or in textual repr: description()558 function description() external view returns (string memory);559560 /// Returns the owner (in cross format) of the token.561 ///562 /// @param tokenId Id for the token.563 /// @dev EVM selector for this function is: 0x2b29dace,564 /// or in textual repr: crossOwnerOf(uint256)565 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);566567 /// Returns the token properties.568 ///569 /// @param tokenId Id for the token.570 /// @param keys Properties keys. Empty keys for all propertyes.571 /// @return Vector of properties key/value pairs.572 /// @dev EVM selector for this function is: 0xe07ede7e,573 /// or in textual repr: properties(uint256,string[])574 function properties(uint256 tokenId, string[] memory keys) external view returns (Property[] memory);575576 /// @notice Transfer ownership of an RFT577 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`578 /// is the zero address. Throws if `tokenId` is not a valid RFT.579 /// Throws if RFT pieces have multiple owners.580 /// @param to The new owner581 /// @param tokenId The RFT to transfer582 /// @dev EVM selector for this function is: 0xa9059cbb,583 /// or in textual repr: transfer(address,uint256)584 function transfer(address to, uint256 tokenId) external;585586 /// @notice Transfer ownership of an RFT587 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`588 /// is the zero address. Throws if `tokenId` is not a valid RFT.589 /// Throws if RFT pieces have multiple owners.590 /// @param to The new owner591 /// @param tokenId The RFT to transfer592 /// @dev EVM selector for this function is: 0x2ada85ff,593 /// or in textual repr: transferCross((address,uint256),uint256)594 function transferCross(EthCrossAccount memory to, uint256 tokenId) external;595596 /// @notice Transfer ownership of an RFT597 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`598 /// is the zero address. Throws if `tokenId` is not a valid RFT.599 /// Throws if RFT pieces have multiple owners.600 /// @param to The new owner601 /// @param tokenId The RFT to transfer602 /// @dev EVM selector for this function is: 0xd5cf430b,603 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)604 function transferFromCross(605 EthCrossAccount memory from,606 EthCrossAccount memory to,607 uint256 tokenId608 ) external;609610 // /// @notice Burns a specific ERC721 token.611 // /// @dev Throws unless `msg.sender` is the current owner or an authorized612 // /// operator for this RFT. Throws if `from` is not the current owner. Throws613 // /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.614 // /// Throws if RFT pieces have multiple owners.615 // /// @param from The current owner of the RFT616 // /// @param tokenId The RFT to transfer617 // /// @dev EVM selector for this function is: 0x79cc6790,618 // /// or in textual repr: burnFrom(address,uint256)619 // function burnFrom(address from, uint256 tokenId) external;620621 /// @notice Burns a specific ERC721 token.622 /// @dev Throws unless `msg.sender` is the current owner or an authorized623 /// operator for this RFT. Throws if `from` is not the current owner. Throws624 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.625 /// Throws if RFT pieces have multiple owners.626 /// @param from The current owner of the RFT627 /// @param tokenId The RFT to transfer628 /// @dev EVM selector for this function is: 0xbb2f5a58,629 /// or in textual repr: burnFromCross((address,uint256),uint256)630 function burnFromCross(EthCrossAccount memory from, uint256 tokenId) external;631632 /// @notice Returns next free RFT ID.633 /// @dev EVM selector for this function is: 0x75794a3c,634 /// or in textual repr: nextTokenId()635 function nextTokenId() external view returns (uint256);636637 // /// @notice Function to mint multiple tokens.638 // /// @dev `tokenIds` should be an array of consecutive numbers and first number639 // /// should be obtained with `nextTokenId` method640 // /// @param to The new owner641 // /// @param tokenIds IDs of the minted RFTs642 // /// @dev EVM selector for this function is: 0x44a9945e,643 // /// or in textual repr: mintBulk(address,uint256[])644 // function mintBulk(address to, uint256[] memory tokenIds) external returns (bool);645646 // /// @notice Function to mint multiple tokens with the given tokenUris.647 // /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive648 // /// numbers and first number should be obtained with `nextTokenId` method649 // /// @param to The new owner650 // /// @param tokens array of pairs of token ID and token URI for minted tokens651 // /// @dev EVM selector for this function is: 0x36543006,652 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])653 // function mintBulkWithTokenURI(address to, Tuple12[] memory tokens) external returns (bool);654655 /// Returns EVM address for refungible token656 ///657 /// @param token ID of the token658 /// @dev EVM selector for this function is: 0xab76fac6,659 /// or in textual repr: tokenContractAddress(uint256)660 function tokenContractAddress(uint256 token) external view returns (address);661}662663/// @dev anonymous struct664struct Tuple12 {665 uint256 field_0;666 string field_1;667}668669/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension670/// @dev See https://eips.ethereum.org/EIPS/eip-721671/// @dev the ERC-165 identifier for this interface is 0x780e9d63672interface ERC721Enumerable is Dummy, ERC165 {673 /// @notice Enumerate valid RFTs674 /// @param index A counter less than `totalSupply()`675 /// @return The token identifier for the `index`th NFT,676 /// (sort order not specified)677 /// @dev EVM selector for this function is: 0x4f6ccce7,678 /// or in textual repr: tokenByIndex(uint256)679 function tokenByIndex(uint256 index) external view returns (uint256);680681 /// Not implemented682 /// @dev EVM selector for this function is: 0x2f745c59,683 /// or in textual repr: tokenOfOwnerByIndex(address,uint256)684 function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);685686 /// @notice Count RFTs tracked by this contract687 /// @return A count of valid RFTs tracked by this contract, where each one of688 /// them has an assigned and queryable owner not equal to the zero address689 /// @dev EVM selector for this function is: 0x18160ddd,690 /// or in textual repr: totalSupply()691 function totalSupply() external view returns (uint256);692}693694/// @dev inlined interface695interface ERC721Events {696 event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);697 event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);698 event ApprovalForAll(address indexed owner, address indexed operator, bool approved);699}700701/// @title ERC-721 Non-Fungible Token Standard702/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md703/// @dev the ERC-165 identifier for this interface is 0x4016cd87704interface ERC721 is Dummy, ERC165, ERC721Events {705 /// @notice Count all RFTs assigned to an owner706 /// @dev RFTs assigned to the zero address are considered invalid, and this707 /// function throws for queries about the zero address.708 /// @param owner An address for whom to query the balance709 /// @return The number of RFTs owned by `owner`, possibly zero710 /// @dev EVM selector for this function is: 0x70a08231,711 /// or in textual repr: balanceOf(address)712 function balanceOf(address owner) external view returns (uint256);713714 /// @notice Find the owner of an RFT715 /// @dev RFTs assigned to zero address are considered invalid, and queries716 /// about them do throw.717 /// Returns special 0xffffffffffffffffffffffffffffffffffffffff address for718 /// the tokens that are partially owned.719 /// @param tokenId The identifier for an RFT720 /// @return The address of the owner of the RFT721 /// @dev EVM selector for this function is: 0x6352211e,722 /// or in textual repr: ownerOf(uint256)723 function ownerOf(uint256 tokenId) external view returns (address);724725 /// @dev Not implemented726 /// @dev EVM selector for this function is: 0x60a11672,727 /// or in textual repr: safeTransferFromWithData(address,address,uint256,bytes)728 function safeTransferFromWithData(729 address from,730 address to,731 uint256 tokenId,732 bytes memory data733 ) external;734735 /// @dev Not implemented736 /// @dev EVM selector for this function is: 0x42842e0e,737 /// or in textual repr: safeTransferFrom(address,address,uint256)738 function safeTransferFrom(739 address from,740 address to,741 uint256 tokenId742 ) external;743744 /// @notice Transfer ownership of an RFT -- THE CALLER IS RESPONSIBLE745 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE746 /// THEY MAY BE PERMANENTLY LOST747 /// @dev Throws unless `msg.sender` is the current owner or an authorized748 /// operator for this RFT. Throws if `from` is not the current owner. Throws749 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.750 /// Throws if RFT pieces have multiple owners.751 /// @param from The current owner of the NFT752 /// @param to The new owner753 /// @param tokenId The NFT to transfer754 /// @dev EVM selector for this function is: 0x23b872dd,755 /// or in textual repr: transferFrom(address,address,uint256)756 function transferFrom(757 address from,758 address to,759 uint256 tokenId760 ) external;761762 /// @dev Not implemented763 /// @dev EVM selector for this function is: 0x095ea7b3,764 /// or in textual repr: approve(address,uint256)765 function approve(address approved, uint256 tokenId) external;766767 /// @notice Sets or unsets the approval of a given operator.768 /// The `operator` is allowed to transfer all token pieces of the `caller` on their behalf.769 /// @param operator Operator770 /// @param approved Should operator status be granted or revoked?771 /// @dev EVM selector for this function is: 0xa22cb465,772 /// or in textual repr: setApprovalForAll(address,bool)773 function setApprovalForAll(address operator, bool approved) external;774775 /// @dev Not implemented776 /// @dev EVM selector for this function is: 0x081812fc,777 /// or in textual repr: getApproved(uint256)778 function getApproved(uint256 tokenId) external view returns (address);779780 /// @notice Tells whether the given `owner` approves the `operator`.781 /// @dev EVM selector for this function is: 0xe985e9c5,782 /// or in textual repr: isApprovedForAll(address,address)783 function isApprovedForAll(address owner, address operator) external view returns (bool);784785 /// @notice Returns collection helper contract address786 /// @dev EVM selector for this function is: 0x1896cce6,787 /// or in textual repr: collectionHelperAddress()788 function collectionHelperAddress() external view returns (address);789}790791interface UniqueRefungible is792 Dummy,793 ERC165,794 ERC721,795 ERC721Enumerable,796 ERC721UniqueExtensions,797 ERC721UniqueMintable,798 ERC721Burnable,799 ERC721Metadata,800 Collection,801 TokenProperties802{}tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -17,7 +17,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {evmToAddress} from '@polkadot/util-crypto';
import {Pallets, requirePalletsOrSkip} from '../util';
-import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
const DECIMALS = 18;
@@ -79,6 +79,56 @@
expect(await collection.methods.description().call()).to.deep.equal(description);
});
+ itEth('Set limits', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'INSI');
+ const limits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: 0,
+ ownerCanDestroy: 0,
+ transfersEnabled: 0,
+ };
+
+ const expectedLimits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: false,
+ ownerCanDestroy: false,
+ transfersEnabled: false,
+ };
+
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
+ await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();
+
+ const data = (await helper.rft.getData(collectionId))!;
+ expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+ expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+ expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+ expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+ expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+ expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+ expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+ expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+ expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
+ });
+
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
@@ -197,6 +247,7 @@
{
await expect(peasantCollection.methods
.setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -224,5 +275,31 @@
.setCollectionLimit('accountTokenOwnershipLimit', '1000')
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
- });
+ });
+
+ itEth('(!negative test!) Set limits', async ({helper}) => {
+
+ const invalidLimits = {
+ accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+ transfersEnabled: 3,
+ };
+
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'ISNI');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
+ await expect(collectionEvm.methods
+ .setCollectionLimit(20, true, '1')
+ .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"');
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)
+ .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)
+ .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
+ });
+
+
+
});
tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -16,7 +16,7 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
-import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
describe('Create NFT collection from EVM', () => {
@@ -120,6 +120,56 @@
expect(await sponsorCollection.methods.description().call()).to.deep.equal(description);
});
+ itEth('Set limits', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');
+ const limits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: 0,
+ ownerCanDestroy: 0,
+ transfersEnabled: 0,
+ };
+
+ const expectedLimits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: false,
+ ownerCanDestroy: false,
+ transfersEnabled: false,
+ };
+
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();
+
+ const data = (await helper.rft.getData(collectionId))!;
+ expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+ expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+ expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+ expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+ expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+ expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+ expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+ expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+ expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
+ });
+
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
@@ -207,7 +257,7 @@
}
{
await expect(malfeasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -232,11 +282,30 @@
}
{
await expect(malfeasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
+ itEth('(!negative test!) Set limits', async ({helper}) => {
+ const invalidLimits = {
+ accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+ transfersEnabled: 3,
+ };
+
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)
+ .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)
+ .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
+ });
+
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -17,7 +17,7 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
import {Pallets, requirePalletsOrSkip} from '../util';
-import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
describe('Create RFT collection from EVM', () => {
@@ -152,6 +152,56 @@
expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
});
+ itEth('Set limits', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'INSI');
+ const limits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: 0,
+ ownerCanDestroy: 0,
+ transfersEnabled: 0,
+ };
+
+ const expectedLimits = {
+ accountTokenOwnershipLimit: 1000,
+ sponsoredDataSize: 1024,
+ sponsoredDataRateLimit: 30,
+ tokenLimit: 1000000,
+ sponsorTransferTimeout: 6,
+ sponsorApproveTimeout: 6,
+ ownerCanTransfer: false,
+ ownerCanDestroy: false,
+ transfersEnabled: false,
+ };
+
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+ await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();
+ await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();
+
+ const data = (await helper.rft.getData(collectionId))!;
+ expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+ expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+ expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+ expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+ expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+ expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+ expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+ expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+ expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
+ });
+
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
@@ -239,7 +289,7 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
@@ -264,10 +314,29 @@
}
{
await expect(peasantCollection.methods
- .setCollectionLimit('accountTokenOwnershipLimit', '1000')
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
}
});
+
+ itEth('(!negative test!) Set limits', async ({helper}) => {
+ const invalidLimits = {
+ accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+ transfersEnabled: 3,
+ };
+
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'ISNI');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)
+ .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+
+ await expect(collectionEvm.methods
+ .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)
+ .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
+ });
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
tests/src/eth/util/index.tsdiffbeforeafterboth--- a/tests/src/eth/util/index.ts
+++ b/tests/src/eth/util/index.ts
@@ -26,6 +26,17 @@
Allowlisted = 1,
Generous = 2,
}
+export enum CollectionLimits {
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled
+}
export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {
const silentConsole = new SilentConsole();