git.delta.rocks / unique-network / refs/commits / 7f98069c7b60

difftreelog

feat Add `collection_admins` method to eth collection.

Trubnikov Sergey2022-10-24parent: #ab2e6a7.patch.diff
in: master

19 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
580580
581 /// Get collection owner.581 /// Get collection owner.
582 ///582 ///
583 /// @return Tuble with sponsor address and his substrate mirror.583 /// @return Tuple with sponsor address and his substrate mirror.
584 /// If address is canonical then substrate mirror is zero and vice versa.584 /// If address is canonical then substrate mirror is zero and vice versa.
585 fn collection_owner(&self) -> Result<(address, uint256)> {585 fn collection_owner(&self) -> Result<(address, uint256)> {
586 Ok(convert_cross_account_to_tuple::<T>(586 Ok(convert_cross_account_to_tuple::<T>(
616 // .map_err(dispatch_to_evm::<T>)616 // .map_err(dispatch_to_evm::<T>)
617 // }617 // }
618618
619 // TODO: need implement AbiWriter for &Vec<T>619 /// Get collection administrators
620 // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {620 ///
621 // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))621 /// @return Vector of tuples with admins address and his substrate mirror.
622 // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))622 /// If address is canonical then substrate mirror is zero and vice versa.
623 // .collect();623 fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
624 // Ok(result)624 let result = crate::IsAdmin::<T>::iter_prefix((self.id,))
625 // }625 .map(|(admin, _)| crate::eth::convert_cross_account_to_tuple::<T>(&admin))
626 .collect();
627 Ok(result)
628 }
626}629}
627630
628/// ### Note631/// ### Note
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows you to work with collections.20/// @title A contract that allows you to work with collections.
21/// @dev the ERC-165 identifier for this interface is 0x62e2229021/// @dev the ERC-165 identifier for this interface is 0x3af103fb
22contract Collection is Dummy, ERC165 {22contract Collection is Dummy, ERC165 {
23 /// Set collection property.23 /// Set collection property.
24 ///24 ///
282282
283 /// Get collection owner.283 /// Get collection owner.
284 ///284 ///
285 /// @return Tuble with sponsor address and his substrate mirror.285 /// @return Tuple with sponsor address and his substrate mirror.
286 /// If address is canonical then substrate mirror is zero and vice versa.286 /// If address is canonical then substrate mirror is zero and vice versa.
287 /// @dev EVM selector for this function is: 0xdf727d3b,287 /// @dev EVM selector for this function is: 0xdf727d3b,
288 /// or in textual repr: collectionOwner()288 /// or in textual repr: collectionOwner()
304 dummy = 0;304 dummy = 0;
305 }305 }
306
307 /// Get collection administrators
308 ///
309 /// @return Vector of tuples with admins address and his substrate mirror.
310 /// If address is canonical then substrate mirror is zero and vice versa.
311 /// @dev EVM selector for this function is: 0x5813216b,
312 /// or in textual repr: collectionAdmins()
313 function collectionAdmins() public view returns (Tuple6[] memory) {
314 require(false, stub_error);
315 dummy;
316 return new Tuple6[](0);
317 }
306}318}
307319
308/// @dev the ERC-165 identifier for this interface is 0x63034ac5320/// @dev the ERC-165 identifier for this interface is 0x63034ac5
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
91}91}
9292
93/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.
94/// @dev the ERC-165 identifier for this interface is 0x62e2229094/// @dev the ERC-165 identifier for this interface is 0x3af103fb
95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {
96 /// Set collection property.96 /// Set collection property.
97 ///97 ///
355355
356 /// Get collection owner.356 /// Get collection owner.
357 ///357 ///
358 /// @return Tuble with sponsor address and his substrate mirror.358 /// @return Tuple with sponsor address and his substrate mirror.
359 /// If address is canonical then substrate mirror is zero and vice versa.359 /// If address is canonical then substrate mirror is zero and vice versa.
360 /// @dev EVM selector for this function is: 0xdf727d3b,360 /// @dev EVM selector for this function is: 0xdf727d3b,
361 /// or in textual repr: collectionOwner()361 /// or in textual repr: collectionOwner()
377 dummy = 0;377 dummy = 0;
378 }378 }
379
380 /// Get collection administrators
381 ///
382 /// @return Vector of tuples with admins address and his substrate mirror.
383 /// If address is canonical then substrate mirror is zero and vice versa.
384 /// @dev EVM selector for this function is: 0x5813216b,
385 /// or in textual repr: collectionAdmins()
386 function collectionAdmins() public view returns (Tuple17[] memory) {
387 require(false, stub_error);
388 dummy;
389 return new Tuple17[](0);
390 }
379}391}
380392
381/// @dev anonymous struct393/// @dev anonymous struct
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
91}91}
9292
93/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.
94/// @dev the ERC-165 identifier for this interface is 0x62e2229094/// @dev the ERC-165 identifier for this interface is 0x3af103fb
95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {
96 /// Set collection property.96 /// Set collection property.
97 ///97 ///
355355
356 /// Get collection owner.356 /// Get collection owner.
357 ///357 ///
358 /// @return Tuble with sponsor address and his substrate mirror.358 /// @return Tuple with sponsor address and his substrate mirror.
359 /// If address is canonical then substrate mirror is zero and vice versa.359 /// If address is canonical then substrate mirror is zero and vice versa.
360 /// @dev EVM selector for this function is: 0xdf727d3b,360 /// @dev EVM selector for this function is: 0xdf727d3b,
361 /// or in textual repr: collectionOwner()361 /// or in textual repr: collectionOwner()
377 dummy = 0;377 dummy = 0;
378 }378 }
379
380 /// Get collection administrators
381 ///
382 /// @return Vector of tuples with admins address and his substrate mirror.
383 /// If address is canonical then substrate mirror is zero and vice versa.
384 /// @dev EVM selector for this function is: 0x5813216b,
385 /// or in textual repr: collectionAdmins()
386 function collectionAdmins() public view returns (Tuple17[] memory) {
387 require(false, stub_error);
388 dummy;
389 return new Tuple17[](0);
390 }
379}391}
380392
381/// @dev anonymous struct393/// @dev anonymous struct
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.
16/// @dev the ERC-165 identifier for this interface is 0x62e2229016/// @dev the ERC-165 identifier for this interface is 0x3af103fb
17interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {
18 /// Set collection property.18 /// Set collection property.
19 ///19 ///
184184
185 /// Get collection owner.185 /// Get collection owner.
186 ///186 ///
187 /// @return Tuble with sponsor address and his substrate mirror.187 /// @return Tuple with sponsor address and his substrate mirror.
188 /// If address is canonical then substrate mirror is zero and vice versa.188 /// If address is canonical then substrate mirror is zero and vice versa.
189 /// @dev EVM selector for this function is: 0xdf727d3b,189 /// @dev EVM selector for this function is: 0xdf727d3b,
190 /// or in textual repr: collectionOwner()190 /// or in textual repr: collectionOwner()
198 /// or in textual repr: changeCollectionOwner(address)198 /// or in textual repr: changeCollectionOwner(address)
199 function changeCollectionOwner(address newOwner) external;199 function changeCollectionOwner(address newOwner) external;
200
201 /// Get collection administrators
202 ///
203 /// @return Vector of tuples with admins address and his substrate mirror.
204 /// If address is canonical then substrate mirror is zero and vice versa.
205 /// @dev EVM selector for this function is: 0x5813216b,
206 /// or in textual repr: collectionAdmins()
207 function collectionAdmins() external view returns (Tuple6[] memory);
200}208}
201209
202/// @dev the ERC-165 identifier for this interface is 0x63034ac5210/// @dev the ERC-165 identifier for this interface is 0x63034ac5
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
62}62}
6363
64/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.
65/// @dev the ERC-165 identifier for this interface is 0x62e2229065/// @dev the ERC-165 identifier for this interface is 0x3af103fb
66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {
67 /// Set collection property.67 /// Set collection property.
68 ///68 ///
233233
234 /// Get collection owner.234 /// Get collection owner.
235 ///235 ///
236 /// @return Tuble with sponsor address and his substrate mirror.236 /// @return Tuple with sponsor address and his substrate mirror.
237 /// If address is canonical then substrate mirror is zero and vice versa.237 /// If address is canonical then substrate mirror is zero and vice versa.
238 /// @dev EVM selector for this function is: 0xdf727d3b,238 /// @dev EVM selector for this function is: 0xdf727d3b,
239 /// or in textual repr: collectionOwner()239 /// or in textual repr: collectionOwner()
247 /// or in textual repr: changeCollectionOwner(address)247 /// or in textual repr: changeCollectionOwner(address)
248 function changeCollectionOwner(address newOwner) external;248 function changeCollectionOwner(address newOwner) external;
249
250 /// Get collection administrators
251 ///
252 /// @return Vector of tuples with admins address and his substrate mirror.
253 /// If address is canonical then substrate mirror is zero and vice versa.
254 /// @dev EVM selector for this function is: 0x5813216b,
255 /// or in textual repr: collectionAdmins()
256 function collectionAdmins() external view returns (Tuple17[] memory);
249}257}
250258
251/// @dev anonymous struct259/// @dev anonymous struct
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
62}62}
6363
64/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.
65/// @dev the ERC-165 identifier for this interface is 0x62e2229065/// @dev the ERC-165 identifier for this interface is 0x3af103fb
66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {
67 /// Set collection property.67 /// Set collection property.
68 ///68 ///
233233
234 /// Get collection owner.234 /// Get collection owner.
235 ///235 ///
236 /// @return Tuble with sponsor address and his substrate mirror.236 /// @return Tuple with sponsor address and his substrate mirror.
237 /// If address is canonical then substrate mirror is zero and vice versa.237 /// If address is canonical then substrate mirror is zero and vice versa.
238 /// @dev EVM selector for this function is: 0xdf727d3b,238 /// @dev EVM selector for this function is: 0xdf727d3b,
239 /// or in textual repr: collectionOwner()239 /// or in textual repr: collectionOwner()
247 /// or in textual repr: changeCollectionOwner(address)247 /// or in textual repr: changeCollectionOwner(address)
248 function changeCollectionOwner(address newOwner) external;248 function changeCollectionOwner(address newOwner) external;
249
250 /// Get collection administrators
251 ///
252 /// @return Vector of tuples with admins address and his substrate mirror.
253 /// If address is canonical then substrate mirror is zero and vice versa.
254 /// @dev EVM selector for this function is: 0x5813216b,
255 /// or in textual repr: collectionAdmins()
256 function collectionAdmins() external view returns (Tuple17[] memory);
249}257}
250258
251/// @dev anonymous struct259/// @dev anonymous struct
modifiedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1515
16import {IKeyringPair} from '@polkadot/types/types';16import {IKeyringPair} from '@polkadot/types/types';
17import {IEthCrossAccountId} from '../util/playgrounds/types';
17import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';18import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';
1819
19async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {20async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {
73 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;75 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;
74 });76 });
7577
78 itEth.skip('Check adminlist', async ({helper}) => {
79 const owner = await helper.eth.createAccountWithBalance(donor);
80
81 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
82 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
83
84 const admin1 = helper.eth.createAccount();
85 const [admin2] = await helper.arrange.createAccounts([10n], donor);
86 await collectionEvm.methods.addCollectionAdmin(admin1).send();
87 await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();
88
89 const adminListRpc = await helper.collection.getAdmins(collectionId);
90 let adminListEth = await collectionEvm.methods.collectionAdmins().call();
91 adminListEth = adminListEth.map((element: IEthCrossAccountId) => {
92 return helper.address.convertCrossAccountFromEthCrossAcoount(element);
93 });
94 expect(adminListRpc).to.be.like(adminListEth);
95 });
96
76 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {97 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {
77 const owner = await helper.eth.createAccountWithBalance(donor);98 const owner = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
124 "stateMutability": "nonpayable",124 "stateMutability": "nonpayable",
125 "type": "function"125 "type": "function"
126 },126 },
127 {
128 "inputs": [],
129 "name": "collectionAdmins",
130 "outputs": [
131 {
132 "components": [
133 { "internalType": "address", "name": "field_0", "type": "address" },
134 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
135 ],
136 "internalType": "struct Tuple6[]",
137 "name": "",
138 "type": "tuple[]"
139 }
140 ],
141 "stateMutability": "view",
142 "type": "function"
143 },
127 {144 {
128 "inputs": [],145 "inputs": [],
129 "name": "collectionOwner",146 "name": "collectionOwner",
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
154 "stateMutability": "nonpayable",154 "stateMutability": "nonpayable",
155 "type": "function"155 "type": "function"
156 },156 },
157 {
158 "inputs": [],
159 "name": "collectionAdmins",
160 "outputs": [
161 {
162 "components": [
163 { "internalType": "address", "name": "field_0", "type": "address" },
164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
165 ],
166 "internalType": "struct Tuple17[]",
167 "name": "",
168 "type": "tuple[]"
169 }
170 ],
171 "stateMutability": "view",
172 "type": "function"
173 },
157 {174 {
158 "inputs": [],175 "inputs": [],
159 "name": "collectionOwner",176 "name": "collectionOwner",
modifiedtests/src/eth/reFungibleAbi.jsondiffbeforeafterboth
154 "stateMutability": "nonpayable",154 "stateMutability": "nonpayable",
155 "type": "function"155 "type": "function"
156 },156 },
157 {
158 "inputs": [],
159 "name": "collectionAdmins",
160 "outputs": [
161 {
162 "components": [
163 { "internalType": "address", "name": "field_0", "type": "address" },
164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
165 ],
166 "internalType": "struct Tuple17[]",
167 "name": "",
168 "type": "tuple[]"
169 }
170 ],
171 "stateMutability": "view",
172 "type": "function"
173 },
157 {174 {
158 "inputs": [],175 "inputs": [],
159 "name": "collectionOwner",176 "name": "collectionOwner",
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
70 ethereum?: TEthereumAccount;70 ethereum?: TEthereumAccount;
71}71}
72
73export interface IEthCrossAccountId {
74 0: TEthereumAccount;
75 1: TSubstrateAccount;
76 field_0: TEthereumAccount;
77 field_1: TSubstrateAccount;
78}
7279
73export interface ICollectionLimits {80export interface ICollectionLimits {
74 accountTokenOwnershipLimit?: number | null;81 accountTokenOwnershipLimit?: number | null;
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
77
8import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';8import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';
9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';
10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';
11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';
12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata} from './types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata, IEthCrossAccountId} from './types';
13import {hexToU8a} from '@polkadot/util/hex';
14import {u8aConcat} from '@polkadot/util/u8a';
1315
14export class CrossAccountId implements ICrossAccountId {16export class CrossAccountId implements ICrossAccountId {
15 Substrate?: TSubstrateAccount;17 Substrate?: TSubstrateAccount;
2310 return siblingPrefix + encodedParaId + suffix;2312 return siblingPrefix + encodedParaId + suffix;
2311 }2313 }
2314
2315 /**
2316 * Encode key to substrate address
2317 * @param key key for encoding address
2318 * @param ss58Format prefix for encoding to the address of the corresponding network
2319 * @returns encoded substrate address
2320 */
2321 encodeSubstrateAddress (key: Uint8Array | string | bigint, ss58Format = 42): string {
2322 const u8a :Uint8Array = typeof key === 'string'
2323 ? hexToU8a(key)
2324 : typeof key === 'bigint'
2325 ? hexToU8a(key.toString(16))
2326 : key;
2327
2328 if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {
2329 throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);
2330 }
2331
2332 const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];
2333 if (!allowedDecodedLengths.includes(u8a.length)) {
2334 throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);
2335 }
2336
2337 const u8aPrefix = ss58Format < 64
2338 ? new Uint8Array([ss58Format])
2339 : new Uint8Array([
2340 ((ss58Format & 0xfc) >> 2) | 0x40,
2341 (ss58Format >> 8) | ((ss58Format & 0x03) << 6),
2342 ]);
2343
2344 const input = u8aConcat(u8aPrefix, u8a);
2345
2346 return base58Encode(u8aConcat(
2347 input,
2348 blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),
2349 ));
2350 }
2351
2352 /**
2353 * Restore substrate address from bigint representation
2354 * @param number decimal representation of substrate address
2355 * @returns substrate address
2356 */
2357 restoreCrossAccountFromBigInt(number: bigint): TSubstrateAccount {
2358 if (this.helper.api === null) {
2359 throw 'Not connected';
2360 }
2361 const res = this.helper.api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();
2362 if (res === undefined || res === null) {
2363 throw 'Restore address error';
2364 }
2365 return res.toString();
2366 }
2367
2368 /**
2369 * Convert etherium cross account id to substrate cross account id
2370 * @param ethCrossAccount etherium cross account
2371 * @returns substrate cross account id
2372 */
2373 convertCrossAccountFromEthCrossAcoount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId {
2374 if (ethCrossAccount.field_1 === '0') {
2375 return {Ethereum: ethCrossAccount.field_0.toLocaleLowerCase()};
2376 }
2377
2378 const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.field_1));
2379 return {Substrate: ss58};
2380 }
2312}2381}
23132382
2314class StakingGroup extends HelperGroup<UniqueHelper> {2383class StakingGroup extends HelperGroup<UniqueHelper> {