difftreelog
added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`
in: master
15 files changed
pallets/common/src/erc.rsdiffbeforeafterboth37 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,37 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,38 eth::{38 eth::{39 EthCrossAccount, convert_cross_account_to_uint256, CollectionPermissions as EvmPermissions,39 EthCrossAccount, convert_cross_account_to_uint256, CollectionPermissions as EvmPermissions,40 CollectionLimits as EvmCollectionLimits,40 },41 },41 weights::WeightInfo,42 weights::WeightInfo,42};43};304 Ok(result)305 Ok(result)305 }306 }307308 /// Get current collection limits.309 ///310 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:311 /// "accountTokenOwnershipLimit",312 /// "sponsoredDataSize",313 /// "sponsoredDataRateLimit",314 /// "tokenLimit",315 /// "sponsorTransferTimeout",316 /// "sponsorApproveTimeout"317 /// "ownerCanTransfer",318 /// "ownerCanDestroy",319 /// "transfersEnabled"320 /// Return `false` if a limit not set.321 fn collection_limits(&self) -> Result<Vec<(EvmCollectionLimits, bool, uint256)>> {322 let convert_value_limit = |limit: EvmCollectionLimits,323 value: Option<u32>|324 -> (EvmCollectionLimits, bool, uint256) {325 value326 .map(|v| (limit, true, v.into()))327 .unwrap_or((limit, false, Default::default()))328 };329330 let convert_bool_limit = |limit: EvmCollectionLimits,331 value: Option<bool>|332 -> (EvmCollectionLimits, bool, uint256) {333 value334 .map(|v| {335 (336 limit,337 true,338 if v {339 uint256::from(1)340 } else {341 Default::default()342 },343 )344 })345 .unwrap_or((limit, false, Default::default()))346 };347348 let limits = &self.collection.limits;349350 Ok(vec![351 convert_value_limit(352 EvmCollectionLimits::AccountTokenOwnership,353 limits.account_token_ownership_limit,354 ),355 convert_value_limit(356 EvmCollectionLimits::SponsoredDataSize,357 limits.sponsored_data_size,358 ),359 limits360 .sponsored_data_rate_limit361 .map(|limit| {362 (363 EvmCollectionLimits::SponsoredDataRateLimit,364 match limit {365 SponsoringRateLimit::Blocks(_) => true,366 _ => false,367 },368 match limit {369 SponsoringRateLimit::Blocks(blocks) => blocks.into(),370 _ => Default::default(),371 },372 )373 })374 .unwrap_or((375 EvmCollectionLimits::SponsoredDataRateLimit,376 false,377 Default::default(),378 )),379 convert_value_limit(EvmCollectionLimits::TokenLimit, limits.token_limit),380 convert_value_limit(381 EvmCollectionLimits::SponsorTransferTimeout,382 limits.sponsor_transfer_timeout,383 ),384 convert_value_limit(385 EvmCollectionLimits::SponsorApproveTimeout,386 limits.sponsor_approve_timeout,387 ),388 convert_bool_limit(389 EvmCollectionLimits::OwnerCanTransfer,390 limits.owner_can_transfer,391 ),392 convert_bool_limit(393 EvmCollectionLimits::OwnerCanDestroy,394 limits.owner_can_destroy,395 ),396 convert_bool_limit(397 EvmCollectionLimits::TransferEnabled,398 limits.transfers_enabled,399 ),400 ])401 }306402307 /// Set limits for the collection.403 /// Set limits for the collection.308 /// @dev Throws error if limit not found.404 /// @dev Throws error if limit not found.318 /// "transfersEnabled"414 /// "transfersEnabled"319 /// @param value Value of the limit.415 /// @param value Value of the limit.320 #[solidity(rename_selector = "setCollectionLimit")]416 #[solidity(rename_selector = "setCollectionLimit")]321 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint256) -> Result<void> {417 fn set_collection_limit(418 &mut self,419 caller: caller,420 limit: EvmCollectionLimits,421 status: bool,422 value: uint256,423 ) -> Result<void> {322 self.consume_store_reads_and_writes(1, 1)?;424 self.consume_store_reads_and_writes(1, 1)?;425426 if !status {427 return Err(Error::Revert("user can't disable limits".into()));428 }323429324 let value = value430 let value = value325 .try_into()431 .try_into()338444339 let mut limits = self.limits.clone();445 let mut limits = self.limits.clone();340446341 match limit.as_str() {447 match limit {342 "accountTokenOwnershipLimit" => {448 EvmCollectionLimits::AccountTokenOwnership => {343 limits.account_token_ownership_limit = Some(value);449 limits.account_token_ownership_limit = Some(value);344 }450 }345 "sponsoredDataSize" => {451 EvmCollectionLimits::SponsoredDataSize => {346 limits.sponsored_data_size = Some(value);452 limits.sponsored_data_size = Some(value);347 }453 }348 "sponsoredDataRateLimit" => {454 EvmCollectionLimits::SponsoredDataRateLimit => {349 limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(value));455 limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(value));350 }456 }351 "tokenLimit" => {457 EvmCollectionLimits::TokenLimit => {352 limits.token_limit = Some(value);458 limits.token_limit = Some(value);353 }459 }354 "sponsorTransferTimeout" => {460 EvmCollectionLimits::SponsorTransferTimeout => {355 limits.sponsor_transfer_timeout = Some(value);461 limits.sponsor_transfer_timeout = Some(value);356 }462 }357 "sponsorApproveTimeout" => {463 EvmCollectionLimits::SponsorApproveTimeout => {358 limits.sponsor_approve_timeout = Some(value);464 limits.sponsor_approve_timeout = Some(value);359 }465 }360 "ownerCanTransfer" => {466 EvmCollectionLimits::OwnerCanTransfer => {361 limits.owner_can_transfer = Some(convert_value_to_bool()?);467 limits.owner_can_transfer = Some(convert_value_to_bool()?);362 }468 }363 "ownerCanDestroy" => {469 EvmCollectionLimits::OwnerCanDestroy => {364 limits.owner_can_destroy = Some(convert_value_to_bool()?);470 limits.owner_can_destroy = Some(convert_value_to_bool()?);365 }471 }366 "transfersEnabled" => {472 EvmCollectionLimits::TransferEnabled => {367 limits.transfers_enabled = Some(convert_value_to_bool()?);473 limits.transfers_enabled = Some(convert_value_to_bool()?);368 }474 }369 _ => return Err(Error::Revert(format!("unknown limit \"{}\"", limit))),475 _ => return Err(Error::Revert(format!("unknown limit \"{:?}\"", limit))),370 }476 }371477372 let caller = T::CrossAccountId::from_eth(caller);478 let caller = T::CrossAccountId::from_eth(caller);779 }885 }780}886}887888fn convert_value_limit<V: Into<uint256> + Copy>(889 limit: EvmCollectionLimits,890 value: &Option<V>,891) -> (EvmCollectionLimits, bool, uint256) {892 value893 .map(|v| (limit, true, v.into()))894 .unwrap_or((limit, false, Default::default()))895}896897fn convert_bool_limit(898 limit: EvmCollectionLimits,899 value: &Option<bool>,900) -> (EvmCollectionLimits, bool, uint256) {901 value902 .map(|v| {903 (904 limit,905 true,906 if v {907 uint256::from(1)908 } else {909 Default::default()910 },911 )912 })913 .unwrap_or((limit, false, Default::default()))914}781915pallets/common/src/eth.rsdiffbeforeafterboth155 }155 }156 }156 }157}157}158#[derive(Debug, Default, Clone, Copy, AbiCoder)]159#[repr(u8)]160pub enum CollectionLimits {161 #[default]162 AccountTokenOwnership,163 SponsoredDataSize,164 SponsoredDataRateLimit,165 TokenLimit,166 SponsorTransferTimeout,167 SponsorApproveTimeout,168 OwnerCanTransfer,169 OwnerCanDestroy,170 TransferEnabled,171}158#[derive(Default, Debug, Clone, Copy, AbiCoder)]172#[derive(Default, Debug, Clone, Copy, AbiCoder)]159#[repr(u8)]173#[repr(u8)]160pub enum CollectionPermissions {174pub enum CollectionPermissions {pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth158 return Tuple8(0x0000000000000000000000000000000000000000, 0);158 return Tuple8(0x0000000000000000000000000000000000000000, 0);159 }159 }160161 /// Get current collection limits.162 ///163 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:164 /// "accountTokenOwnershipLimit",165 /// "sponsoredDataSize",166 /// "sponsoredDataRateLimit",167 /// "tokenLimit",168 /// "sponsorTransferTimeout",169 /// "sponsorApproveTimeout"170 /// "ownerCanTransfer",171 /// "ownerCanDestroy",172 /// "transfersEnabled"173 /// Return `false` if a limit not set.174 /// @dev EVM selector for this function is: 0xf63bc572,175 /// or in textual repr: collectionLimits()176 function collectionLimits() public view returns (Tuple20[] memory) {177 require(false, stub_error);178 dummy;179 return new Tuple20[](0);180 }160181161 /// Set limits for the collection.182 /// Set limits for the collection.162 /// @dev Throws error if limit not found.183 /// @dev Throws error if limit not found.171 /// "ownerCanDestroy",192 /// "ownerCanDestroy",172 /// "transfersEnabled"193 /// "transfersEnabled"173 /// @param value Value of the limit.194 /// @param value Value of the limit.174 /// @dev EVM selector for this function is: 0x4ad890a8,195 /// @dev EVM selector for this function is: 0x88150bd0,175 /// or in textual repr: setCollectionLimit(string,uint256)196 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)176 function setCollectionLimit(string memory limit, uint256 value) public {197 function setCollectionLimit(198 CollectionLimits limit,199 bool status,200 uint256 value201 ) public {177 require(false, stub_error);202 require(false, stub_error);178 limit;203 limit;204 status;179 value;205 value;180 dummy = 0;206 dummy = 0;181 }207 }pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth291 return Tuple30(0x0000000000000000000000000000000000000000, 0);291 return Tuple30(0x0000000000000000000000000000000000000000, 0);292 }292 }293294 /// Get current collection limits.295 ///296 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:297 /// "accountTokenOwnershipLimit",298 /// "sponsoredDataSize",299 /// "sponsoredDataRateLimit",300 /// "tokenLimit",301 /// "sponsorTransferTimeout",302 /// "sponsorApproveTimeout"303 /// "ownerCanTransfer",304 /// "ownerCanDestroy",305 /// "transfersEnabled"306 /// Return `false` if a limit not set.307 /// @dev EVM selector for this function is: 0xf63bc572,308 /// or in textual repr: collectionLimits()309 function collectionLimits() public view returns (Tuple33[] memory) {310 require(false, stub_error);311 dummy;312 return new Tuple33[](0);313 }293314294 /// Set limits for the collection.315 /// Set limits for the collection.295 /// @dev Throws error if limit not found.316 /// @dev Throws error if limit not found.304 /// "ownerCanDestroy",325 /// "ownerCanDestroy",305 /// "transfersEnabled"326 /// "transfersEnabled"306 /// @param value Value of the limit.327 /// @param value Value of the limit.307 /// @dev EVM selector for this function is: 0x4ad890a8,328 /// @dev EVM selector for this function is: 0x88150bd0,308 /// or in textual repr: setCollectionLimit(string,uint256)329 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)309 function setCollectionLimit(string memory limit, uint256 value) public {330 function setCollectionLimit(331 CollectionLimits limit,332 bool status,333 uint256 value334 ) public {310 require(false, stub_error);335 require(false, stub_error);311 limit;336 limit;337 status;312 value;338 value;313 dummy = 0;339 dummy = 0;314 }340 }pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth292 return Tuple29(0x0000000000000000000000000000000000000000, 0);292 return Tuple29(0x0000000000000000000000000000000000000000, 0);293 }293 }294295 /// Get current collection limits.296 ///297 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:298 /// "accountTokenOwnershipLimit",299 /// "sponsoredDataSize",300 /// "sponsoredDataRateLimit",301 /// "tokenLimit",302 /// "sponsorTransferTimeout",303 /// "sponsorApproveTimeout"304 /// "ownerCanTransfer",305 /// "ownerCanDestroy",306 /// "transfersEnabled"307 /// Return `false` if a limit not set.308 /// @dev EVM selector for this function is: 0xf63bc572,309 /// or in textual repr: collectionLimits()310 function collectionLimits() public view returns (Tuple32[] memory) {311 require(false, stub_error);312 dummy;313 return new Tuple32[](0);314 }294315295 /// Set limits for the collection.316 /// Set limits for the collection.296 /// @dev Throws error if limit not found.317 /// @dev Throws error if limit not found.305 /// "ownerCanDestroy",326 /// "ownerCanDestroy",306 /// "transfersEnabled"327 /// "transfersEnabled"307 /// @param value Value of the limit.328 /// @param value Value of the limit.308 /// @dev EVM selector for this function is: 0x4ad890a8,329 /// @dev EVM selector for this function is: 0x88150bd0,309 /// or in textual repr: setCollectionLimit(string,uint256)330 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)310 function setCollectionLimit(string memory limit, uint256 value) public {331 function setCollectionLimit(332 CollectionLimits limit,333 bool status,334 uint256 value335 ) public {311 require(false, stub_error);336 require(false, stub_error);312 limit;337 limit;338 status;313 value;339 value;314 dummy = 0;340 dummy = 0;315 }341 }tests/src/eth/abi/fungible.jsondiffbeforeafterboth208 },208 },209 {209 {210 "inputs": [],210 "inputs": [],211<<<<<<< HEAD211 "name": "collectionNestingPermissions",212 "name": "collectionNestingPermissions",213=======214 "name": "collectionLimits",215>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`212 "outputs": [216 "outputs": [213 {217 {214 "components": [218 "components": [215 {219 {220<<<<<<< HEAD216 "internalType": "enum CollectionPermissions",221 "internalType": "enum CollectionPermissions",217 "name": "field_0",222 "name": "field_0",218 "type": "uint8"223 "type": "uint8"219 },224 },220 { "internalType": "bool", "name": "field_1", "type": "bool" }225 { "internalType": "bool", "name": "field_1", "type": "bool" }221 ],226 ],222 "internalType": "struct Tuple24[]",227 "internalType": "struct Tuple24[]",228=======229 "internalType": "enum CollectionLimits",230 "name": "field_0",231 "type": "uint8"232 },233 { "internalType": "bool", "name": "field_1", "type": "bool" },234 { "internalType": "uint256", "name": "field_2", "type": "uint256" }235 ],236 "internalType": "struct Tuple20[]",237>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`223 "name": "",238 "name": "",224 "type": "tuple[]"239 "type": "tuple[]"225 }240 }229 },244 },230 {245 {231 "inputs": [],246 "inputs": [],247<<<<<<< HEAD232 "name": "collectionNestingRestrictedCollectionIds",248 "name": "collectionNestingRestrictedCollectionIds",233 "outputs": [249 "outputs": [234 {250 {250 },266 },251 {267 {252 "inputs": [],268 "inputs": [],269=======270>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`253 "name": "collectionOwner",271 "name": "collectionOwner",254 "outputs": [272 "outputs": [255 {273 {453 },471 },454 {472 {455 "inputs": [473 "inputs": [456 { "internalType": "string", "name": "limit", "type": "string" },474 {475 "internalType": "enum CollectionLimits",476 "name": "limit",477 "type": "uint8"478 },479 { "internalType": "bool", "name": "status", "type": "bool" },457 { "internalType": "uint256", "name": "value", "type": "uint256" }480 { "internalType": "uint256", "name": "value", "type": "uint256" }458 ],481 ],459 "name": "setCollectionLimit",482 "name": "setCollectionLimit",tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth607 },607 },608 {608 {609 "inputs": [609 "inputs": [610 { "internalType": "string", "name": "limit", "type": "string" },610 {611 "internalType": "enum CollectionLimits",612 "name": "limit",613 "type": "uint8"614 },615 { "internalType": "bool", "name": "status", "type": "bool" },611 { "internalType": "uint256", "name": "value", "type": "uint256" }616 { "internalType": "uint256", "name": "value", "type": "uint256" }612 ],617 ],613 "name": "setCollectionLimit",618 "name": "setCollectionLimit",tests/src/eth/abi/reFungible.jsondiffbeforeafterboth589 },589 },590 {590 {591 "inputs": [591 "inputs": [592 { "internalType": "string", "name": "limit", "type": "string" },592 {593 "internalType": "enum CollectionLimits",594 "name": "limit",595 "type": "uint8"596 },597 { "internalType": "bool", "name": "status", "type": "bool" },593 { "internalType": "uint256", "name": "value", "type": "uint256" }598 { "internalType": "uint256", "name": "value", "type": "uint256" }594 ],599 ],595 "name": "setCollectionLimit",600 "name": "setCollectionLimit",tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth13}13}141415/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.16<<<<<<< HEAD16/// @dev the ERC-165 identifier for this interface is 0xb5e1747f17/// @dev the ERC-165 identifier for this interface is 0xb5e1747f18=======19/// @dev the ERC-165 identifier for this interface is 0xf8ebdec020>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`17interface Collection is Dummy, ERC165 {21interface Collection is Dummy, ERC165 {18 // /// Set collection property.22 // /// Set collection property.19 // ///23 // ///104 /// or in textual repr: collectionSponsor()108 /// or in textual repr: collectionSponsor()105 function collectionSponsor() external view returns (Tuple8 memory);109 function collectionSponsor() external view returns (Tuple8 memory);106110111 /// Get current collection limits.112 ///113 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:114 /// "accountTokenOwnershipLimit",115 /// "sponsoredDataSize",116 /// "sponsoredDataRateLimit",117 /// "tokenLimit",118 /// "sponsorTransferTimeout",119 /// "sponsorApproveTimeout"120 /// "ownerCanTransfer",121 /// "ownerCanDestroy",122 /// "transfersEnabled"123 /// Return `false` if a limit not set.124 /// @dev EVM selector for this function is: 0xf63bc572,125 /// or in textual repr: collectionLimits()126 function collectionLimits() external view returns (Tuple19[] memory);127107 /// Set limits for the collection.128 /// Set limits for the collection.108 /// @dev Throws error if limit not found.129 /// @dev Throws error if limit not found.109 /// @param limit Name of the limit. Valid names:130 /// @param limit Name of the limit. Valid names:117 /// "ownerCanDestroy",138 /// "ownerCanDestroy",118 /// "transfersEnabled"139 /// "transfersEnabled"119 /// @param value Value of the limit.140 /// @param value Value of the limit.120 /// @dev EVM selector for this function is: 0x4ad890a8,141 /// @dev EVM selector for this function is: 0x88150bd0,121 /// or in textual repr: setCollectionLimit(string,uint256)142 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)122 function setCollectionLimit(string memory limit, uint256 value) external;143 function setCollectionLimit(144 CollectionLimits limit,145 bool status,146 uint256 value147 ) external;123148124 /// Get contract address.149 /// Get contract address.125 /// @dev EVM selector for this function is: 0xf6b4dfb4,150 /// @dev EVM selector for this function is: 0xf6b4dfb4,288 uint256 sub;313 uint256 sub;289}314}290315316<<<<<<< HEAD291/// @dev anonymous struct317/// @dev anonymous struct292struct Tuple23 {318struct Tuple23 {293 CollectionPermissions field_0;319 CollectionPermissions field_0;303struct Tuple20 {329struct Tuple20 {304 bool field_0;330 bool field_0;305 uint256[] field_1;331 uint256[] field_1;332=======333enum CollectionLimits {334 AccountTokenOwnership,335 SponsoredDataSize,336 SponsoredDataRateLimit,337 TokenLimit,338 SponsorTransferTimeout,339 SponsorApproveTimeout,340 OwnerCanTransfer,341 OwnerCanDestroy,342 TransferEnabled343}344345/// @dev anonymous struct346struct Tuple19 {347 CollectionLimits field_0;348 bool field_1;349 uint256 field_2;350>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`306}351}307352308/// @dev Property struct353/// @dev Property structtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth104}104}105105106/// @title A contract that allows you to work with collections.106/// @title A contract that allows you to work with collections.107<<<<<<< HEAD107/// @dev the ERC-165 identifier for this interface is 0xb5e1747f108/// @dev the ERC-165 identifier for this interface is 0xb5e1747f109=======110/// @dev the ERC-165 identifier for this interface is 0xf8ebdec0111>>>>>>> 32e011ce... added `collectionLimits` function in `Collection` interface, changed signture for `setCollectionLimit`108interface Collection is Dummy, ERC165 {112interface Collection is Dummy, ERC165 {109 // /// Set collection property.113 // /// Set collection property.110 // ///114 // ///195 /// or in textual repr: collectionSponsor()199 /// or in textual repr: collectionSponsor()196 function collectionSponsor() external view returns (Tuple27 memory);200 function collectionSponsor() external view returns (Tuple27 memory);197201202 /// Get current collection limits.203 ///204 /// @return Array of tuples (byte, bool, uint256) with limits and their values. Order of limits:205 /// "accountTokenOwnershipLimit",206 /// "sponsoredDataSize",207 /// "sponsoredDataRateLimit",208 /// "tokenLimit",209 /// "sponsorTransferTimeout",210 /// "sponsorApproveTimeout"211 /// "ownerCanTransfer",212 /// "ownerCanDestroy",213 /// "transfersEnabled"214 /// Return `false` if a limit not set.215 /// @dev EVM selector for this function is: 0xf63bc572,216 /// or in textual repr: collectionLimits()217 function collectionLimits() external view returns (Tuple30[] memory);218198 /// Set limits for the collection.219 /// Set limits for the collection.199 /// @dev Throws error if limit not found.220 /// @dev Throws error if limit not found.200 /// @param limit Name of the limit. Valid names:221 /// @param limit Name of the limit. Valid names:208 /// "ownerCanDestroy",229 /// "ownerCanDestroy",209 /// "transfersEnabled"230 /// "transfersEnabled"210 /// @param value Value of the limit.231 /// @param value Value of the limit.211 /// @dev EVM selector for this function is: 0x4ad890a8,232 /// @dev EVM selector for this function is: 0x88150bd0,212 /// or in textual repr: setCollectionLimit(string,uint256)233 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)213 function setCollectionLimit(string memory limit, uint256 value) external;234 function setCollectionLimit(235 CollectionLimits limit,236 bool status,237 uint256 value238 ) external;214239215 /// Get contract address.240 /// Get contract address.216 /// @dev EVM selector for this function is: 0xf6b4dfb4,241 /// @dev EVM selector for this function is: 0xf6b4dfb4,377struct EthCrossAccount {402struct EthCrossAccount {378 address eth;403 address eth;379 uint256 sub;404 uint256 sub;405}406407enum CollectionLimits {408 AccountTokenOwnership,409 SponsoredDataSize,410 SponsoredDataRateLimit,411 TokenLimit,412 SponsorTransferTimeout,413 SponsorApproveTimeout,414 OwnerCanTransfer,415 OwnerCanDestroy,416 TransferEnabled417}418419/// @dev anonymous struct420struct Tuple30 {421 CollectionLimits field_0;422 bool field_1;423 uint256 field_2;380}424}381425382/// @dev anonymous struct426/// @dev anonymous structtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth105}105}106106107/// @title A contract that allows you to work with collections.107/// @title A contract that allows you to work with collections.108<<<<<<< HEAD108/// @dev the ERC-165 identifier for this interface is 0xb5e1747f109/// @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`109interface Collection is Dummy, ERC165 {113interface Collection is Dummy, ERC165 {110 // /// Set collection property.114 // /// Set collection property.111 // ///115 // ///196 /// or in textual repr: collectionSponsor()200 /// or in textual repr: collectionSponsor()197 function collectionSponsor() external view returns (Tuple26 memory);201 function collectionSponsor() external view returns (Tuple26 memory);198202203 /// 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);219199 /// Set limits for the collection.220 /// Set limits for the collection.200 /// @dev Throws error if limit not found.221 /// @dev Throws error if limit not found.201 /// @param limit Name of the limit. Valid names:222 /// @param limit Name of the limit. Valid names:209 /// "ownerCanDestroy",230 /// "ownerCanDestroy",210 /// "transfersEnabled"231 /// "transfersEnabled"211 /// @param value Value of the limit.232 /// @param value Value of the limit.212 /// @dev EVM selector for this function is: 0x4ad890a8,233 /// @dev EVM selector for this function is: 0x88150bd0,213 /// or in textual repr: setCollectionLimit(string,uint256)234 /// or in textual repr: setCollectionLimit(uint8,bool,uint256)214 function setCollectionLimit(string memory limit, uint256 value) external;235 function setCollectionLimit(236 CollectionLimits limit,237 bool status,238 uint256 value239 ) external;215240216 /// Get contract address.241 /// Get contract address.217 /// @dev EVM selector for this function is: 0xf6b4dfb4,242 /// @dev EVM selector for this function is: 0xf6b4dfb4,378struct EthCrossAccount {403struct EthCrossAccount {379 address eth;404 address eth;380 uint256 sub;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;381}425}382426383/// @dev anonymous struct427/// @dev anonymous structtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {evmToAddress} from '@polkadot/util-crypto';18import {evmToAddress} from '@polkadot/util-crypto';19import {Pallets, requirePalletsOrSkip} from '../util';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';20import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';212122const DECIMALS = 18;22const DECIMALS = 18;232379 expect(await collection.methods.description().call()).to.deep.equal(description);79 expect(await collection.methods.description().call()).to.deep.equal(description);80 });80 });8182 itEth('Set limits', async ({helper}) => {83 const owner = await helper.eth.createAccountWithBalance(donor);84 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'INSI');85 const limits = {86 accountTokenOwnershipLimit: 1000,87 sponsoredDataSize: 1024,88 sponsoredDataRateLimit: 30,89 tokenLimit: 1000000,90 sponsorTransferTimeout: 6,91 sponsorApproveTimeout: 6,92 ownerCanTransfer: 0,93 ownerCanDestroy: 0,94 transfersEnabled: 0,95 };96 97 const expectedLimits = {98 accountTokenOwnershipLimit: 1000,99 sponsoredDataSize: 1024,100 sponsoredDataRateLimit: 30,101 tokenLimit: 1000000,102 sponsorTransferTimeout: 6,103 sponsorApproveTimeout: 6,104 ownerCanTransfer: false,105 ownerCanDestroy: false,106 transfersEnabled: false,107 };108 109 const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);110 await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();111 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();112 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();113 await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();114 await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();115 await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();116 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();117 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();118 await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();119 120 const data = (await helper.rft.getData(collectionId))!;121 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);122 expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);123 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);124 expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);125 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);126 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);127 expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);128 expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);129 expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);130 });8113182 itEth('Collection address exist', async ({helper}) => {132 itEth('Collection address exist', async ({helper}) => {83 const owner = await helper.eth.createAccountWithBalance(donor);133 const owner = await helper.eth.createAccountWithBalance(donor);197 {247 {198 await expect(peasantCollection.methods248 await expect(peasantCollection.methods199 .setCollectionLimit('accountTokenOwnershipLimit', '1000')249 .setCollectionLimit('accountTokenOwnershipLimit', '1000')250 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)200 .call()).to.be.rejectedWith(EXPECTED_ERROR);251 .call()).to.be.rejectedWith(EXPECTED_ERROR);201 }252 }202 });253 });226 }277 }227 }); 278 });279280 itEth('(!negative test!) Set limits', async ({helper}) => {281282 const invalidLimits = {283 accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),284 transfersEnabled: 3,285 };286287 const owner = await helper.eth.createAccountWithBalance(donor);288 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'ISNI');289 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);290 await expect(collectionEvm.methods291 .setCollectionLimit(20, true, '1')292 .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"');293 294 await expect(collectionEvm.methods295 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)296 .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);297 298 await expect(collectionEvm.methods299 .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)300 .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);301 });302303 304 tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth161617import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {expect, itEth, usingEthPlaygrounds} from './util';19import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';2020212122describe('Create NFT collection from EVM', () => {22describe('Create NFT collection from EVM', () => {120 expect(await sponsorCollection.methods.description().call()).to.deep.equal(description);120 expect(await sponsorCollection.methods.description().call()).to.deep.equal(description);121 });121 });122123 itEth('Set limits', async ({helper}) => {124 const owner = await helper.eth.createAccountWithBalance(donor);125 const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');126 const limits = {127 accountTokenOwnershipLimit: 1000,128 sponsoredDataSize: 1024,129 sponsoredDataRateLimit: 30,130 tokenLimit: 1000000,131 sponsorTransferTimeout: 6,132 sponsorApproveTimeout: 6,133 ownerCanTransfer: 0,134 ownerCanDestroy: 0,135 transfersEnabled: 0,136 };137 138 const expectedLimits = {139 accountTokenOwnershipLimit: 1000,140 sponsoredDataSize: 1024,141 sponsoredDataRateLimit: 30,142 tokenLimit: 1000000,143 sponsorTransferTimeout: 6,144 sponsorApproveTimeout: 6,145 ownerCanTransfer: false,146 ownerCanDestroy: false,147 transfersEnabled: false,148 };149150 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);151 await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();152 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();153 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();154 await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();155 await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();156 await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();157 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();158 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();159 await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();160161 const data = (await helper.rft.getData(collectionId))!;162 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);163 expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);164 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);165 expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);166 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);167 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);168 expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);169 expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);170 expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);171 });122172123 itEth('Collection address exist', async ({helper}) => {173 itEth('Collection address exist', async ({helper}) => {124 const owner = await helper.eth.createAccountWithBalance(donor);174 const owner = await helper.eth.createAccountWithBalance(donor);207 }257 }208 {258 {209 await expect(malfeasantCollection.methods259 await expect(malfeasantCollection.methods210 .setCollectionLimit('accountTokenOwnershipLimit', '1000')260 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)211 .call()).to.be.rejectedWith(EXPECTED_ERROR);261 .call()).to.be.rejectedWith(EXPECTED_ERROR);212 }262 }213 });263 });232 }282 }233 {283 {234 await expect(malfeasantCollection.methods284 await expect(malfeasantCollection.methods235 .setCollectionLimit('accountTokenOwnershipLimit', '1000')285 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)236 .call()).to.be.rejectedWith(EXPECTED_ERROR);286 .call()).to.be.rejectedWith(EXPECTED_ERROR);237 }287 }238 });288 });289290 itEth('(!negative test!) Set limits', async ({helper}) => {291 const invalidLimits = {292 accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),293 transfersEnabled: 3,294 };295296 const owner = await helper.eth.createAccountWithBalance(donor);297 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');298 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);299 300 await expect(collectionEvm.methods301 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)302 .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);303 304 await expect(collectionEvm.methods305 .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)306 .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);307 });239308240 itEth('destroyCollection', async ({helper}) => {309 itEth('destroyCollection', async ({helper}) => {241 const owner = await helper.eth.createAccountWithBalance(donor);310 const owner = await helper.eth.createAccountWithBalance(donor);tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';20import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';2121222223describe('Create RFT collection from EVM', () => {23describe('Create RFT collection from EVM', () => {152 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));152 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));153 });153 });154155 itEth('Set limits', async ({helper}) => {156 const owner = await helper.eth.createAccountWithBalance(donor);157 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'INSI');158 const limits = {159 accountTokenOwnershipLimit: 1000,160 sponsoredDataSize: 1024,161 sponsoredDataRateLimit: 30,162 tokenLimit: 1000000,163 sponsorTransferTimeout: 6,164 sponsorApproveTimeout: 6,165 ownerCanTransfer: 0,166 ownerCanDestroy: 0,167 transfersEnabled: 0,168 };169 170 const expectedLimits = {171 accountTokenOwnershipLimit: 1000,172 sponsoredDataSize: 1024,173 sponsoredDataRateLimit: 30,174 tokenLimit: 1000000,175 sponsorTransferTimeout: 6,176 sponsorApproveTimeout: 6,177 ownerCanTransfer: false,178 ownerCanDestroy: false,179 transfersEnabled: false,180 };181 182 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);183 await collection.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send();184 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send();185 await collection.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send();186 await collection.methods.setCollectionLimit(CollectionLimits.TokenLimit, true, limits.tokenLimit).send();187 await collection.methods.setCollectionLimit(CollectionLimits.SponsorTransferTimeout, true, limits.sponsorTransferTimeout).send();188 await collection.methods.setCollectionLimit(CollectionLimits.SponsorApproveTimeout, true, limits.sponsorApproveTimeout).send();189 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send();190 await collection.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send();191 await collection.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send();192 193 const data = (await helper.rft.getData(collectionId))!;194 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);195 expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);196 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);197 expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);198 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);199 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);200 expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);201 expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);202 expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);203 });154204155 itEth('Collection address exist', async ({helper}) => {205 itEth('Collection address exist', async ({helper}) => {156 const owner = await helper.eth.createAccountWithBalance(donor);206 const owner = await helper.eth.createAccountWithBalance(donor);239 }289 }240 {290 {241 await expect(peasantCollection.methods291 await expect(peasantCollection.methods242 .setCollectionLimit('accountTokenOwnershipLimit', '1000')292 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)243 .call()).to.be.rejectedWith(EXPECTED_ERROR);293 .call()).to.be.rejectedWith(EXPECTED_ERROR);244 }294 }245 });295 });264 }314 }265 {315 {266 await expect(peasantCollection.methods316 await expect(peasantCollection.methods267 .setCollectionLimit('accountTokenOwnershipLimit', '1000')317 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)268 .call()).to.be.rejectedWith(EXPECTED_ERROR);318 .call()).to.be.rejectedWith(EXPECTED_ERROR);269 }319 }270 });320 });271 321322 itEth('(!negative test!) Set limits', async ({helper}) => {323 const invalidLimits = {324 accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),325 transfersEnabled: 3,326 };327328 const owner = await helper.eth.createAccountWithBalance(donor);329 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'ISNI');330 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);331 332 await expect(collectionEvm.methods333 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit)334 .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);335 336 await expect(collectionEvm.methods337 .setCollectionLimit(CollectionLimits.TransferEnabled, true, invalidLimits.transfersEnabled)338 .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);339 });340 272 itEth('destroyCollection', async ({helper}) => {341 itEth('destroyCollection', async ({helper}) => {273 const owner = await helper.eth.createAccountWithBalance(donor);342 const owner = await helper.eth.createAccountWithBalance(donor);tests/src/eth/util/index.tsdiffbeforeafterboth26 Allowlisted = 1,26 Allowlisted = 1,27 Generous = 2,27 Generous = 2,28}28}29export enum CollectionLimits {30 AccountTokenOwnership,31 SponsoredDataSize,32 SponsoredDataRateLimit,33 TokenLimit,34 SponsorTransferTimeout,35 SponsorApproveTimeout,36 OwnerCanTransfer,37 OwnerCanDestroy,38 TransferEnabled39}294030export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {41export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {31 const silentConsole = new SilentConsole();42 const silentConsole = new SilentConsole();