From 6e6dff56f54595d4de1fbb0dd6ec8daf938c5f08 Mon Sep 17 00:00:00 2001 From: PraetorP Date: Tue, 08 Nov 2022 09:45:43 +0000 Subject: [PATCH] added coderTest via Conract --- --- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol +++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: OTHER +// This code is automatically generated + +pragma solidity >=0.8.0 <0.9.0; + +/// @dev common stubs holder +contract Dummy { + uint8 dummy; + string stub_error = "this contract is implemented in native"; +} + +contract ERC165 is Dummy { + function supportsInterface(bytes4 interfaceID) external view returns (bool) { + require(false, stub_error); + interfaceID; + return true; + } +} + +/// @dev inlined interface +contract CollectionHelpersEvents { + event CollectionCreated(address indexed owner, address indexed collectionId); + event CollectionDestroyed(address indexed collectionId); +} + +/// @title Contract, which allows users to operate with collections +/// @dev the ERC-165 identifier for this interface is 0x7dea03b1 +contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { + /// Create an NFT collection + /// @param name Name of the collection + /// @param description Informative description of the collection + /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications + /// @return address Address of the newly created collection + /// @dev EVM selector for this function is: 0x844af658, + /// or in textual repr: createNFTCollection(string,string,string) + function createNFTCollection( + string memory name, + string memory description, + string memory tokenPrefix + ) public payable returns (address) { + require(false, stub_error); + name; + description; + tokenPrefix; + dummy = 0; + return 0x0000000000000000000000000000000000000000; + } + + // /// Create an NFT collection + // /// @param name Name of the collection + // /// @param description Informative description of the collection + // /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications + // /// @return address Address of the newly created collection + // /// @dev EVM selector for this function is: 0xe34a6844, + // /// or in textual repr: createNonfungibleCollection(string,string,string) + // function createNonfungibleCollection(string memory name, string memory description, string memory tokenPrefix) public payable returns (address) { + // require(false, stub_error); + // name; + // description; + // tokenPrefix; + // dummy = 0; + // return 0x0000000000000000000000000000000000000000; + // } + + /// @dev EVM selector for this function is: 0xab173450, + /// or in textual repr: createRFTCollection(string,string,string) + function createRFTCollection( + string memory name, + string memory description, + string memory tokenPrefix + ) public payable returns (address) { + require(false, stub_error); + name; + description; + tokenPrefix; + dummy = 0; + return 0x0000000000000000000000000000000000000000; + } + + /// @dev EVM selector for this function is: 0x7335b79f, + /// or in textual repr: createFTCollection(string,uint8,string,string) + function createFTCollection( + string memory name, + uint8 decimals, + string memory description, + string memory tokenPrefix + ) public payable returns (address) { + require(false, stub_error); + name; + decimals; + description; + tokenPrefix; + dummy = 0; + return 0x0000000000000000000000000000000000000000; + } + + /// @dev EVM selector for this function is: 0x85624258, + /// or in textual repr: makeCollectionERC721MetadataCompatible(address,string) + function makeCollectionERC721MetadataCompatible(address collection, string memory baseUri) public { + require(false, stub_error); + collection; + baseUri; + dummy = 0; + } + + /// @dev EVM selector for this function is: 0x564e321f, + /// or in textual repr: destroyCollection(address) + function destroyCollection(address collectionAddress) public { + require(false, stub_error); + collectionAddress; + dummy = 0; + } + + /// Check if a collection exists + /// @param collectionAddress Address of the collection in question + /// @return bool Does the collection exist? + /// @dev EVM selector for this function is: 0xc3de1494, + /// or in textual repr: isCollectionExist(address) + function isCollectionExist(address collectionAddress) public view returns (bool) { + require(false, stub_error); + collectionAddress; + dummy; + return false; + } + + /// @dev EVM selector for this function is: 0xd23a7ab1, + /// or in textual repr: collectionCreationFee() + function collectionCreationFee() public view returns (uint256) { + require(false, stub_error); + dummy; + return 0; + } +} --- a/tests/src/eth/evmToSubstrate/EvmToSubstrateHelper.sol +++ b/tests/src/eth/evmToSubstrate/EvmToSubstrateHelper.sol @@ -68,7 +68,7 @@ if (collectionType == REFUNGIBLE_COLLECTION_TYPE) { UniqueRefungible rftCollection = UniqueRefungible(_collection); - + tokenId = rftCollection.mint(address(this)); rftCollection.transferFromCross( @@ -176,4 +176,27 @@ emit MintToSub(address(0), _substrateReceiver, _collection, tokenId); } + + function proxyProperties( + address _collection, + uint256 _tokenId, + NftProperty[] calldata _properties + ) external checkRestrictions(_collection) { + uint256 propertiesLength = _properties.length; + require(propertiesLength > 0, "Properies is empty"); + + Collection commonContract = Collection(_collection); + bytes32 collectionType = keccak256(bytes(commonContract.uniqueCollectionType())); + + if (collectionType == REFUNGIBLE_COLLECTION_TYPE) { + revert("Wrong collection type. Works only with NFT or RFT"); + } else if (collectionType == NONFUNGIBLE_COLLECTION_TYPE) { + UniqueNFT nftCollection = UniqueNFT(_collection); + + + nftCollection.setProperties(_tokenId, _properties); + } else { + revert("Wrong collection type. Works only with NFT or RFT"); + } + } } --- /dev/null +++ b/tests/src/eth/evmToSubstrate/coderTest.ts @@ -0,0 +1,215 @@ +import { EthUniqueHelper, usingEthPlaygrounds } from '../util'; +import { readFile } from 'fs/promises'; +import { ContractImports } from '../util/playgrounds/types'; +import { Contract } from '@polkadot/api-contract/base'; +import Web3 from 'web3'; +import { + IProperty, + ITokenPropertyPermission, +} from '../../util/playgrounds/types'; +import { addressToEvm, decodeAddress } from '@polkadot/util-crypto'; +import nonFungibleAbi from '../nonFungibleAbi.json'; +import { IKeyringPair } from '@polkadot/types/types'; + +enum SponsoringMode { + Disabled = 0, + Allowlisted = 1, + Generous = 2, +} + +const WS_ENDPOINT = 'wss://ws-rc.unique.network'; +const CONTRACT_IMPORT: ContractImports[] = [ + { + fsPath: `${__dirname}/../api/CollectionHelpers.sol`, + solPath: 'api/CollectionHelpers.sol', + }, + { + fsPath: `${__dirname}/../api/ContractHelpers.sol`, + solPath: 'api/ContractHelpers.sol', + }, + { + fsPath: `${__dirname}/../api/UniqueRefungibleToken.sol`, + solPath: 'api/UniqueRefungibleToken.sol', + }, + { + fsPath: `${__dirname}/../api/UniqueRefungible.sol`, + solPath: 'api/UniqueRefungible.sol', + }, + { + fsPath: `${__dirname}/../api/UniqueNFT.sol`, + solPath: 'api/UniqueNFT.sol', + }, +]; + +const main = async () => { + await usingEthPlaygrounds(async (helper, privateKey) => { + const contract_source = ( + await readFile(`${__dirname}/EvmToSubstrateHelper.sol`) + ).toString(); + + const donor = await privateKey('//Alice'); // Seed from account with balance on this network + const myAccount = await privateKey('//Bob'); // replace with account from polkadot extension + const signer = await helper.eth.createAccountWithBalance(donor, 100n); + console.log(`signer data: ${Uint8Array.from(Buffer.from(signer.slice(2), 'hex'))}`) + const collection = await helper.nft.mintCollection(donor, { + name: 'test mintToSubstrate', + description: 'EVMHelpers', + tokenPrefix: 'ap', + tokenPropertyPermissions: [ + { + key: 'url', + permission: { + tokenOwner: true, + collectionAdmin: true, + mutable: true, + }, + }, + ], + limits: { sponsorTransferTimeout: 0, sponsorApproveTimeout: 0 }, + permissions: { mintMode: true }, + }); + + await collection.addToAllowList(donor, { + Ethereum: helper.address.substrateToEth(donor.address), + }); + await collection.addToAllowList(donor, { Substrate: donor.address }); + await collection.addAdmin(donor, { Ethereum: signer }); + await collection.addAdmin(donor, { + Ethereum: helper.address.substrateToEth(donor.address), + }); + + console.log('collection admin(s)): ', await collection.getAdmins()); + console.log('collection owner(s)): ', await collection.getAllowList()); + + const collectionEthAddress = helper.ethAddress.fromCollectionId( + collection.collectionId, + ); + + const collectionEthContract = helper.ethNativeContract.collection( + collectionEthAddress, + 'nft', + ); + + const receiverEthAddress = helper.address.substrateToEth(myAccount.address); + + const contract = await helper.ethContract.deployByCode( + signer, + 'EvmToSubstrate', + contract_source, + CONTRACT_IMPORT, + ); + console.log(`contract has been deployed\naddres: ${contract.options.address} || ${Uint8Array.from(Buffer.from(contract.options.address.slice(2), 'hex'))}`); + + await helper.eth.transferBalanceFromSubstrate( + donor, + contract.options.address, + 100n, + ); + + console.log(`transfer has been completed`); + + await collection.addToAllowList(donor, { + Ethereum: contract.options.address, + }); + await collection.addAdmin(donor, { Ethereum: contract.options.address }); + + console.log(`setup has been completed`); + + console.log('\t\t\t *** Properties Fees ***\n'); + + const propertiesNumber = 20; + + const properties = Array(40) + .fill(0) + .map((_, i) => { + return { + key: `key_${i}`, + value: Uint8Array.from(Buffer.from(`value_${i}`)), + }; + }); + + const permissions: ITokenPropertyPermission[] = properties.map((p) => { + return { + key: p.key, + permission: { + tokenOwner: true, + collectionAdmin: true, + mutable: true, + }, + }; + }); + + // *** ProxyContract Bulk *** + + const token = await collection.mintToken(donor, { Ethereum: signer }); + + const mintWithBulkPropProxyContractFee = await helper.arrange.calculcateFee( + { Ethereum: signer }, + async () => { + await contract.methods + .proxyProperties( + collectionEthContract.options.address, + token.tokenId, + properties.slice(0, propertiesNumber).map((p) => { + return { field_0: p.key, field_1: p.value }; + }), + ) + .send({ from: signer }); + }, + ); + console.log( + `token mint from contract(with bulk prop.) to the Substrate Id: ${mintWithBulkPropProxyContractFee}`, + ); + + console.log('All done'); + }); +}; + +main() + .then(() => process.exit(0)) + .catch((e) => { + console.log(e); + process.exit(1); + }); + +async function createCollectionForPropertiesBenchmarks( + helper: EthUniqueHelper, + privateKey: (seed: string) => Promise, + ethSigner: string, + proxyContract: string, + permissions: ITokenPropertyPermission[], +) { + const donor = await privateKey('//Alice'); // Seed from account with balance on this network + + const collection = await helper.nft.mintCollection(donor, { + name: 'test mintToSubstrate', + description: 'EVMHelpers', + tokenPrefix: 'ap', + tokenPropertyPermissions: [ + { + key: 'url', + permission: { + tokenOwner: true, + collectionAdmin: true, + mutable: true, + }, + }, + ], + limits: { sponsorTransferTimeout: 0, sponsorApproveTimeout: 0 }, + permissions: { mintMode: true }, + }); + + await collection.addToAllowList(donor, { + Ethereum: helper.address.substrateToEth(donor.address), + }); + await collection.addToAllowList(donor, { Substrate: donor.address }); + await collection.addAdmin(donor, { Ethereum: ethSigner }); + await collection.addAdmin(donor, { + Ethereum: helper.address.substrateToEth(donor.address), + }); + await collection.addToAllowList(donor, { Ethereum: proxyContract }); + await collection.addAdmin(donor, { Ethereum: proxyContract }); + await collection.setTokenPropertyPermissions(donor, permissions); + + return collection; +} -- gitstuff