git.delta.rocks / unique-network / refs/commits / 3903c8aaf16e

difftreelog

CORE-386 Add admin tests

Trubnikov Sergey2022-06-07parent: #b484237.patch.diff
in: master

5 files changed

modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
before · pallets/nonfungible/src/stubs/UniqueNFT.sol
1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56// Anonymous struct7struct Tuple0 {8	uint256 field_0;9	string field_1;10}1112// Common stubs holder13contract Dummy {14	uint8 dummy;15	string stub_error = "this contract is implemented in native";16}1718contract ERC165 is Dummy {19	function supportsInterface(bytes4 interfaceID)20		external21		view22		returns (bool)23	{24		require(false, stub_error);25		interfaceID;26		return true;27	}28}2930// Inline31contract ERC721Events {32	event Transfer(33		address indexed from,34		address indexed to,35		uint256 indexed tokenId36	);37	event Approval(38		address indexed owner,39		address indexed approved,40		uint256 indexed tokenId41	);42	event ApprovalForAll(43		address indexed owner,44		address indexed operator,45		bool approved46	);47}4849// Inline50contract ERC721MintableEvents {51	event MintingFinished();52}5354// Selector: 4136937755contract TokenProperties is Dummy, ERC165 {56	// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa57	function setTokenPropertyPermission(58		string memory key,59		bool isMutable,60		bool collectionAdmin,61		bool tokenOwner62	) public {63		require(false, stub_error);64		key;65		isMutable;66		collectionAdmin;67		tokenOwner;68		dummy = 0;69	}7071	// Selector: setProperty(uint256,string,bytes) 1752d67b72	function setProperty(73		uint256 tokenId,74		string memory key,75		bytes memory value76	) public {77		require(false, stub_error);78		tokenId;79		key;80		value;81		dummy = 0;82	}8384	// Selector: deleteProperty(uint256,string) 066111d185	function deleteProperty(uint256 tokenId, string memory key) public {86		require(false, stub_error);87		tokenId;88		key;89		dummy = 0;90	}9192	// Throws error if key not found93	//94	// Selector: property(uint256,string) 7228c32795	function property(uint256 tokenId, string memory key)96		public97		view98		returns (bytes memory)99	{100		require(false, stub_error);101		tokenId;102		key;103		dummy;104		return hex"";105	}106}107108// Selector: 42966c68109contract ERC721Burnable is Dummy, ERC165 {110	// Selector: burn(uint256) 42966c68111	function burn(uint256 tokenId) public {112		require(false, stub_error);113		tokenId;114		dummy = 0;115	}116}117118// Selector: 58800161119contract ERC721 is Dummy, ERC165, ERC721Events {120	// Selector: balanceOf(address) 70a08231121	function balanceOf(address owner) public view returns (uint256) {122		require(false, stub_error);123		owner;124		dummy;125		return 0;126	}127128	// Selector: ownerOf(uint256) 6352211e129	function ownerOf(uint256 tokenId) public view returns (address) {130		require(false, stub_error);131		tokenId;132		dummy;133		return 0x0000000000000000000000000000000000000000;134	}135136	// Not implemented137	//138	// Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672139	function safeTransferFromWithData(140		address from,141		address to,142		uint256 tokenId,143		bytes memory data144	) public {145		require(false, stub_error);146		from;147		to;148		tokenId;149		data;150		dummy = 0;151	}152153	// Not implemented154	//155	// Selector: safeTransferFrom(address,address,uint256) 42842e0e156	function safeTransferFrom(157		address from,158		address to,159		uint256 tokenId160	) public {161		require(false, stub_error);162		from;163		to;164		tokenId;165		dummy = 0;166	}167168	// Selector: transferFrom(address,address,uint256) 23b872dd169	function transferFrom(170		address from,171		address to,172		uint256 tokenId173	) public {174		require(false, stub_error);175		from;176		to;177		tokenId;178		dummy = 0;179	}180181	// Selector: approve(address,uint256) 095ea7b3182	function approve(address approved, uint256 tokenId) public {183		require(false, stub_error);184		approved;185		tokenId;186		dummy = 0;187	}188189	// Not implemented190	//191	// Selector: setApprovalForAll(address,bool) a22cb465192	function setApprovalForAll(address operator, bool approved) public {193		require(false, stub_error);194		operator;195		approved;196		dummy = 0;197	}198199	// Not implemented200	//201	// Selector: getApproved(uint256) 081812fc202	function getApproved(uint256 tokenId) public view returns (address) {203		require(false, stub_error);204		tokenId;205		dummy;206		return 0x0000000000000000000000000000000000000000;207	}208209	// Not implemented210	//211	// Selector: isApprovedForAll(address,address) e985e9c5212	function isApprovedForAll(address owner, address operator)213		public214		view215		returns (address)216	{217		require(false, stub_error);218		owner;219		operator;220		dummy;221		return 0x0000000000000000000000000000000000000000;222	}223}224225// Selector: 5b5e139f226contract ERC721Metadata is Dummy, ERC165 {227	// Selector: name() 06fdde03228	function name() public view returns (string memory) {229		require(false, stub_error);230		dummy;231		return "";232	}233234	// Selector: symbol() 95d89b41235	function symbol() public view returns (string memory) {236		require(false, stub_error);237		dummy;238		return "";239	}240241	// Returns token's const_metadata242	//243	// Selector: tokenURI(uint256) c87b56dd244	function tokenURI(uint256 tokenId) public view returns (string memory) {245		require(false, stub_error);246		tokenId;247		dummy;248		return "";249	}250}251252// Selector: 68ccfe89253contract ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {254	// Selector: mintingFinished() 05d2035b255	function mintingFinished() public view returns (bool) {256		require(false, stub_error);257		dummy;258		return false;259	}260261	// `token_id` should be obtained with `next_token_id` method,262	// unlike standard, you can't specify it manually263	//264	// Selector: mint(address,uint256) 40c10f19265	function mint(address to, uint256 tokenId) public returns (bool) {266		require(false, stub_error);267		to;268		tokenId;269		dummy = 0;270		return false;271	}272273	// `token_id` should be obtained with `next_token_id` method,274	// unlike standard, you can't specify it manually275	//276	// Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f277	function mintWithTokenURI(278		address to,279		uint256 tokenId,280		string memory tokenUri281	) public returns (bool) {282		require(false, stub_error);283		to;284		tokenId;285		tokenUri;286		dummy = 0;287		return false;288	}289290	// Not implemented291	//292	// Selector: finishMinting() 7d64bcb4293	function finishMinting() public returns (bool) {294		require(false, stub_error);295		dummy = 0;296		return false;297	}298}299300// Selector: 780e9d63301contract ERC721Enumerable is Dummy, ERC165 {302	// Selector: tokenByIndex(uint256) 4f6ccce7303	function tokenByIndex(uint256 index) public view returns (uint256) {304		require(false, stub_error);305		index;306		dummy;307		return 0;308	}309310	// Not implemented311	//312	// Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59313	function tokenOfOwnerByIndex(address owner, uint256 index)314		public315		view316		returns (uint256)317	{318		require(false, stub_error);319		owner;320		index;321		dummy;322		return 0;323	}324325	// Selector: totalSupply() 18160ddd326	function totalSupply() public view returns (uint256) {327		require(false, stub_error);328		dummy;329		return 0;330	}331}332333// Selector: d74d154f334contract ERC721UniqueExtensions is Dummy, ERC165 {335	// Selector: transfer(address,uint256) a9059cbb336	function transfer(address to, uint256 tokenId) public {337		require(false, stub_error);338		to;339		tokenId;340		dummy = 0;341	}342343	// Selector: burnFrom(address,uint256) 79cc6790344	function burnFrom(address from, uint256 tokenId) public {345		require(false, stub_error);346		from;347		tokenId;348		dummy = 0;349	}350351	// Selector: nextTokenId() 75794a3c352	function nextTokenId() public view returns (uint256) {353		require(false, stub_error);354		dummy;355		return 0;356	}357358	// Selector: mintBulk(address,uint256[]) 44a9945e359	function mintBulk(address to, uint256[] memory tokenIds)360		public361		returns (bool)362	{363		require(false, stub_error);364		to;365		tokenIds;366		dummy = 0;367		return false;368	}369370	// Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006371	function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)372		public373		returns (bool)374	{375		require(false, stub_error);376		to;377		tokens;378		dummy = 0;379		return false;380	}381}382383// Selector: f56cd7fa384contract Collection is Dummy, ERC165 {385	// Selector: setCollectionProperty(string,bytes) 2f073f66386	function setCollectionProperty(string memory key, bytes memory value)387		public388	{389		require(false, stub_error);390		key;391		value;392		dummy = 0;393	}394395	// Selector: deleteCollectionProperty(string) 7b7debce396	function deleteCollectionProperty(string memory key) public {397		require(false, stub_error);398		key;399		dummy = 0;400	}401402	// Throws error if key not found403	//404	// Selector: collectionProperty(string) cf24fd6d405	function collectionProperty(string memory key)406		public407		view408		returns (bytes memory)409	{410		require(false, stub_error);411		key;412		dummy;413		return hex"";414	}415416	// Selector: ethSetSponsor(address) 8f9af356417	function ethSetSponsor(address sponsor) public {418		require(false, stub_error);419		sponsor;420		dummy = 0;421	}422423	// Selector: ethConfirmSponsorship() a8580d1a424	function ethConfirmSponsorship() public {425		require(false, stub_error);426		dummy = 0;427	}428429	// Selector: setLimit(string,uint32) 68db30ca430	function setLimit(string memory limit, uint32 value) public {431		require(false, stub_error);432		limit;433		value;434		dummy = 0;435	}436437	// Selector: setLimit(string,bool) ea67e4c2438	function setLimit(string memory limit, bool value) public {439		require(false, stub_error);440		limit;441		value;442		dummy = 0;443	}444445	// Selector: contractAddress() f6b4dfb4446	function contractAddress() public view returns (address) {447		require(false, stub_error);448		dummy;449		return 0x0000000000000000000000000000000000000000;450	}451452	// Selector: addAdmin(address) 70480275453	function addAdmin(address newAdmin) public view {454		require(false, stub_error);455		newAdmin;456		dummy;457	}458459	// Selector: removeAdmin(address) 1785f53c460	function removeAdmin(address admin) public view {461		require(false, stub_error);462		admin;463		dummy;464	}465466	// Selector: setNesting(bool) e8fc50dd467	function setNesting(bool enable) public {468		require(false, stub_error);469		enable;470		dummy = 0;471	}472473	// Selector: setNesting(bool,address[]) 7df12a9a474	function setNesting(bool enable, address[] memory collections) public {475		require(false, stub_error);476		enable;477		collections;478		dummy = 0;479	}480481	// Selector: setAccess(string) 488f56aa482	function setAccess(string memory mode) public {483		require(false, stub_error);484		mode;485		dummy = 0;486	}487488	// Selector: addToAllowList(address) 31f59102489	function addToAllowList(address user) public view {490		require(false, stub_error);491		user;492		dummy;493	}494495	// Selector: removeFromAllowList(address) eba8dabc496	function removeFromAllowList(address user) public view {497		require(false, stub_error);498		user;499		dummy;500	}501502	// Selector: setMintMode(bool) 5dea9bd5503	function setMintMode(bool mode) public {504		require(false, stub_error);505		mode;506		dummy = 0;507	}508}509510contract UniqueNFT is511	Dummy,512	ERC165,513	ERC721,514	ERC721Metadata,515	ERC721Enumerable,516	ERC721UniqueExtensions,517	ERC721Mintable,518	ERC721Burnable,519	Collection,520	TokenProperties521{}
after · pallets/nonfungible/src/stubs/UniqueNFT.sol
1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56// Anonymous struct7struct Tuple0 {8	uint256 field_0;9	string field_1;10}1112// Common stubs holder13contract Dummy {14	uint8 dummy;15	string stub_error = "this contract is implemented in native";16}1718contract ERC165 is Dummy {19	function supportsInterface(bytes4 interfaceID)20		external21		view22		returns (bool)23	{24		require(false, stub_error);25		interfaceID;26		return true;27	}28}2930// Inline31contract ERC721Events {32	event Transfer(33		address indexed from,34		address indexed to,35		uint256 indexed tokenId36	);37	event Approval(38		address indexed owner,39		address indexed approved,40		uint256 indexed tokenId41	);42	event ApprovalForAll(43		address indexed owner,44		address indexed operator,45		bool approved46	);47}4849// Inline50contract ERC721MintableEvents {51	event MintingFinished();52}5354// Selector: 4136937755contract TokenProperties is Dummy, ERC165 {56	// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa57	function setTokenPropertyPermission(58		string memory key,59		bool isMutable,60		bool collectionAdmin,61		bool tokenOwner62	) public {63		require(false, stub_error);64		key;65		isMutable;66		collectionAdmin;67		tokenOwner;68		dummy = 0;69	}7071	// Selector: setProperty(uint256,string,bytes) 1752d67b72	function setProperty(73		uint256 tokenId,74		string memory key,75		bytes memory value76	) public {77		require(false, stub_error);78		tokenId;79		key;80		value;81		dummy = 0;82	}8384	// Selector: deleteProperty(uint256,string) 066111d185	function deleteProperty(uint256 tokenId, string memory key) public {86		require(false, stub_error);87		tokenId;88		key;89		dummy = 0;90	}9192	// Throws error if key not found93	//94	// Selector: property(uint256,string) 7228c32795	function property(uint256 tokenId, string memory key)96		public97		view98		returns (bytes memory)99	{100		require(false, stub_error);101		tokenId;102		key;103		dummy;104		return hex"";105	}106}107108// Selector: 42966c68109contract ERC721Burnable is Dummy, ERC165 {110	// Selector: burn(uint256) 42966c68111	function burn(uint256 tokenId) public {112		require(false, stub_error);113		tokenId;114		dummy = 0;115	}116}117118// Selector: 58800161119contract ERC721 is Dummy, ERC165, ERC721Events {120	// Selector: balanceOf(address) 70a08231121	function balanceOf(address owner) public view returns (uint256) {122		require(false, stub_error);123		owner;124		dummy;125		return 0;126	}127128	// Selector: ownerOf(uint256) 6352211e129	function ownerOf(uint256 tokenId) public view returns (address) {130		require(false, stub_error);131		tokenId;132		dummy;133		return 0x0000000000000000000000000000000000000000;134	}135136	// Not implemented137	//138	// Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672139	function safeTransferFromWithData(140		address from,141		address to,142		uint256 tokenId,143		bytes memory data144	) public {145		require(false, stub_error);146		from;147		to;148		tokenId;149		data;150		dummy = 0;151	}152153	// Not implemented154	//155	// Selector: safeTransferFrom(address,address,uint256) 42842e0e156	function safeTransferFrom(157		address from,158		address to,159		uint256 tokenId160	) public {161		require(false, stub_error);162		from;163		to;164		tokenId;165		dummy = 0;166	}167168	// Selector: transferFrom(address,address,uint256) 23b872dd169	function transferFrom(170		address from,171		address to,172		uint256 tokenId173	) public {174		require(false, stub_error);175		from;176		to;177		tokenId;178		dummy = 0;179	}180181	// Selector: approve(address,uint256) 095ea7b3182	function approve(address approved, uint256 tokenId) public {183		require(false, stub_error);184		approved;185		tokenId;186		dummy = 0;187	}188189	// Not implemented190	//191	// Selector: setApprovalForAll(address,bool) a22cb465192	function setApprovalForAll(address operator, bool approved) public {193		require(false, stub_error);194		operator;195		approved;196		dummy = 0;197	}198199	// Not implemented200	//201	// Selector: getApproved(uint256) 081812fc202	function getApproved(uint256 tokenId) public view returns (address) {203		require(false, stub_error);204		tokenId;205		dummy;206		return 0x0000000000000000000000000000000000000000;207	}208209	// Not implemented210	//211	// Selector: isApprovedForAll(address,address) e985e9c5212	function isApprovedForAll(address owner, address operator)213		public214		view215		returns (address)216	{217		require(false, stub_error);218		owner;219		operator;220		dummy;221		return 0x0000000000000000000000000000000000000000;222	}223}224225// Selector: 5b5e139f226contract ERC721Metadata is Dummy, ERC165 {227	// Selector: name() 06fdde03228	function name() public view returns (string memory) {229		require(false, stub_error);230		dummy;231		return "";232	}233234	// Selector: symbol() 95d89b41235	function symbol() public view returns (string memory) {236		require(false, stub_error);237		dummy;238		return "";239	}240241	// Returns token's const_metadata242	//243	// Selector: tokenURI(uint256) c87b56dd244	function tokenURI(uint256 tokenId) public view returns (string memory) {245		require(false, stub_error);246		tokenId;247		dummy;248		return "";249	}250}251252// Selector: 68ccfe89253contract ERC721Mintable is Dummy, ERC165, ERC721MintableEvents {254	// Selector: mintingFinished() 05d2035b255	function mintingFinished() public view returns (bool) {256		require(false, stub_error);257		dummy;258		return false;259	}260261	// `token_id` should be obtained with `next_token_id` method,262	// unlike standard, you can't specify it manually263	//264	// Selector: mint(address,uint256) 40c10f19265	function mint(address to, uint256 tokenId) public returns (bool) {266		require(false, stub_error);267		to;268		tokenId;269		dummy = 0;270		return false;271	}272273	// `token_id` should be obtained with `next_token_id` method,274	// unlike standard, you can't specify it manually275	//276	// Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f277	function mintWithTokenURI(278		address to,279		uint256 tokenId,280		string memory tokenUri281	) public returns (bool) {282		require(false, stub_error);283		to;284		tokenId;285		tokenUri;286		dummy = 0;287		return false;288	}289290	// Not implemented291	//292	// Selector: finishMinting() 7d64bcb4293	function finishMinting() public returns (bool) {294		require(false, stub_error);295		dummy = 0;296		return false;297	}298}299300// Selector: 780e9d63301contract ERC721Enumerable is Dummy, ERC165 {302	// Selector: tokenByIndex(uint256) 4f6ccce7303	function tokenByIndex(uint256 index) public view returns (uint256) {304		require(false, stub_error);305		index;306		dummy;307		return 0;308	}309310	// Not implemented311	//312	// Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59313	function tokenOfOwnerByIndex(address owner, uint256 index)314		public315		view316		returns (uint256)317	{318		require(false, stub_error);319		owner;320		index;321		dummy;322		return 0;323	}324325	// Selector: totalSupply() 18160ddd326	function totalSupply() public view returns (uint256) {327		require(false, stub_error);328		dummy;329		return 0;330	}331}332333// Selector: 7d9262e6334contract Collection is Dummy, ERC165 {335	// Selector: setCollectionProperty(string,bytes) 2f073f66336	function setCollectionProperty(string memory key, bytes memory value)337		public338	{339		require(false, stub_error);340		key;341		value;342		dummy = 0;343	}344345	// Selector: deleteCollectionProperty(string) 7b7debce346	function deleteCollectionProperty(string memory key) public {347		require(false, stub_error);348		key;349		dummy = 0;350	}351352	// Throws error if key not found353	//354	// Selector: collectionProperty(string) cf24fd6d355	function collectionProperty(string memory key)356		public357		view358		returns (bytes memory)359	{360		require(false, stub_error);361		key;362		dummy;363		return hex"";364	}365366	// Selector: ethSetSponsor(address) 8f9af356367	function ethSetSponsor(address sponsor) public {368		require(false, stub_error);369		sponsor;370		dummy = 0;371	}372373	// Selector: ethConfirmSponsorship() a8580d1a374	function ethConfirmSponsorship() public {375		require(false, stub_error);376		dummy = 0;377	}378379	// Selector: setLimit(string,uint32) 68db30ca380	function setLimit(string memory limit, uint32 value) public {381		require(false, stub_error);382		limit;383		value;384		dummy = 0;385	}386387	// Selector: setLimit(string,bool) ea67e4c2388	function setLimit(string memory limit, bool value) public {389		require(false, stub_error);390		limit;391		value;392		dummy = 0;393	}394395	// Selector: contractAddress() f6b4dfb4396	function contractAddress() public view returns (address) {397		require(false, stub_error);398		dummy;399		return 0x0000000000000000000000000000000000000000;400	}401402	// Selector: addCollectionAdminSubstrate(uint256) 5730062b403	function addCollectionAdminSubstrate(uint256 newAdmin) public view {404		require(false, stub_error);405		newAdmin;406		dummy;407	}408409	// Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9410	function removeCollectionAdminSubstrate(uint256 newAdmin) public view {411		require(false, stub_error);412		newAdmin;413		dummy;414	}415416	// Selector: addCollectionAdmin(address) 92e462c7417	function addCollectionAdmin(address newAdmin) public view {418		require(false, stub_error);419		newAdmin;420		dummy;421	}422423	// Selector: removeAdmin(address) 1785f53c424	function removeAdmin(address admin) public view {425		require(false, stub_error);426		admin;427		dummy;428	}429430	// Selector: setNesting(bool) e8fc50dd431	function setNesting(bool enable) public {432		require(false, stub_error);433		enable;434		dummy = 0;435	}436437	// Selector: setNesting(bool,address[]) 7df12a9a438	function setNesting(bool enable, address[] memory collections) public {439		require(false, stub_error);440		enable;441		collections;442		dummy = 0;443	}444445	// Selector: setAccess(string) 488f56aa446	function setAccess(string memory mode) public {447		require(false, stub_error);448		mode;449		dummy = 0;450	}451452	// Selector: addToAllowList(address) 31f59102453	function addToAllowList(address user) public view {454		require(false, stub_error);455		user;456		dummy;457	}458459	// Selector: removeFromAllowList(address) eba8dabc460	function removeFromAllowList(address user) public view {461		require(false, stub_error);462		user;463		dummy;464	}465466	// Selector: setMintMode(bool) 5dea9bd5467	function setMintMode(bool mode) public {468		require(false, stub_error);469		mode;470		dummy = 0;471	}472}473474// Selector: d74d154f475contract ERC721UniqueExtensions is Dummy, ERC165 {476	// Selector: transfer(address,uint256) a9059cbb477	function transfer(address to, uint256 tokenId) public {478		require(false, stub_error);479		to;480		tokenId;481		dummy = 0;482	}483484	// Selector: burnFrom(address,uint256) 79cc6790485	function burnFrom(address from, uint256 tokenId) public {486		require(false, stub_error);487		from;488		tokenId;489		dummy = 0;490	}491492	// Selector: nextTokenId() 75794a3c493	function nextTokenId() public view returns (uint256) {494		require(false, stub_error);495		dummy;496		return 0;497	}498499	// Selector: mintBulk(address,uint256[]) 44a9945e500	function mintBulk(address to, uint256[] memory tokenIds)501		public502		returns (bool)503	{504		require(false, stub_error);505		to;506		tokenIds;507		dummy = 0;508		return false;509	}510511	// Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006512	function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)513		public514		returns (bool)515	{516		require(false, stub_error);517		to;518		tokens;519		dummy = 0;520		return false;521	}522}523524contract UniqueNFT is525	Dummy,526	ERC165,527	ERC721,528	ERC721Metadata,529	ERC721Enumerable,530	ERC721UniqueExtensions,531	ERC721Mintable,532	ERC721Burnable,533	Collection,534	TokenProperties535{}
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -191,6 +191,70 @@
 	function totalSupply() external view returns (uint256);
 }
 
+// Selector: 7d9262e6
+interface Collection is Dummy, ERC165 {
+	// Selector: setCollectionProperty(string,bytes) 2f073f66
+	function setCollectionProperty(string memory key, bytes memory value)
+		external;
+
+	// Selector: deleteCollectionProperty(string) 7b7debce
+	function deleteCollectionProperty(string memory key) external;
+
+	// Throws error if key not found
+	//
+	// Selector: collectionProperty(string) cf24fd6d
+	function collectionProperty(string memory key)
+		external
+		view
+		returns (bytes memory);
+
+	// Selector: setCollectionSponsor(address) 7623402e
+	function setCollectionSponsor(address sponsor) external;
+
+	// Selector: confirmCollectionSponsorship() 3c50e97a
+	function confirmCollectionSponsorship() external;
+
+	// Selector: setCollectionLimit(string,uint32) 6a3841db
+	function setCollectionLimit(string memory limit, uint32 value) external;
+
+	// Selector: setCollectionLimit(string,bool) 993b7fba
+	function setCollectionLimit(string memory limit, bool value) external;
+
+	// Selector: contractAddress() f6b4dfb4
+	function contractAddress() external view returns (address);
+
+	// Selector: addCollectionAdminSubstrate(uint256) 5730062b
+	function addCollectionAdminSubstrate(uint256 newAdmin) external view;
+
+	// Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
+	function removeCollectionAdminSubstrate(uint256 newAdmin) external view;
+
+	// Selector: addCollectionAdmin(address) 92e462c7
+	function addCollectionAdmin(address newAdmin) external view;
+
+	// Selector: removeCollectionAdmin(address) fafd7b42
+	function removeCollectionAdmin(address admin) external view;
+
+	// Selector: setCollectionNesting(bool) 112d4586
+	function setCollectionNesting(bool enable) external;
+
+	// Selector: setCollectionNesting(bool,address[]) 64872396
+	function setCollectionNesting(bool enable, address[] memory collections)
+		external;
+
+	// Selector: setCollectionAccess(uint8) 41835d4c
+	function setCollectionAccess(uint8 mode) external;
+
+	// Selector: addToCollectionAllowList(address) 67844fe6
+	function addToCollectionAllowList(address user) external view;
+
+	// Selector: removeFromCollectionAllowList(address) 85c51acb
+	function removeFromCollectionAllowList(address user) external view;
+
+	// Selector: setCollectionMintMode(bool) 00018e84
+	function setCollectionMintMode(bool mode) external;
+}
+
 // Selector: d74d154f
 interface ERC721UniqueExtensions is Dummy, ERC165 {
 	// Selector: transfer(address,uint256) a9059cbb
addedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -0,0 +1,88 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+import {expect} from 'chai';
+import privateKey from '../substrate/privateKey';
+import {
+  createEthAccount,
+  createEthAccountWithBalance, 
+  evmCollection, 
+  evmCollectionHelpers, 
+  getCollectionAddressFromResult, 
+  itWeb3,
+} from './util/helpers';
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+describe.only('Add collection admins', () => {
+  itWeb3('Add admin by owner', async ({api, web3}) => {
+    const owner = await createEthAccountWithBalance(api, web3);
+    const collectionHelper = evmCollectionHelpers(web3, owner);
+        
+    const result = await collectionHelper.methods
+      .createNonfungibleCollection('A', 'B', 'C')
+      .send();
+    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+    const newAdmin = await createEthAccount(web3);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
+    const adminList = await api.rpc.unique.adminlist(collectionId);
+    expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+      .to.be.eq(newAdmin.toLocaleLowerCase());
+  });
+
+  itWeb3('Add substrate admin by owner', async ({api, web3}) => {
+    const owner = await createEthAccountWithBalance(api, web3);
+    const collectionHelper = evmCollectionHelpers(web3, owner);
+        
+    const result = await collectionHelper.methods
+      .createNonfungibleCollection('A', 'B', 'C')
+      .send();
+    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+    const newAdmin = privateKey('//Alice');
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();
+    const adminList = await api.rpc.unique.adminlist(collectionId);
+    expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
+      .to.be.eq(newAdmin.address.toLocaleLowerCase());
+  });
+
+  itWeb3('(!negative tests!) Add admin by admin is not allowed', async ({api, web3}) => {
+    const owner = await createEthAccountWithBalance(api, web3);
+    const collectionHelper = evmCollectionHelpers(web3, owner);
+        
+    const result = await collectionHelper.methods
+      .createNonfungibleCollection('A', 'B', 'C')
+      .send();
+    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+    const admin = await createEthAccountWithBalance(api, web3);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    await collectionEvm.methods.addCollectionAdmin(admin).send();
+    {
+      const adminList = await api.rpc.unique.adminlist(collectionId);
+      expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+        .to.be.eq(admin.toLocaleLowerCase());
+    }
+    
+    const user = await createEthAccount(web3);
+    await collectionEvm.methods.addCollectionAdmin(user).send({from: admin});
+    const adminList = await api.rpc.unique.adminlist(collectionId);
+    expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+      .to.be.eq(admin.toLocaleLowerCase());
+    expect(adminList.length).to.be.eq(1);
+  });
+});
\ No newline at end of file
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -91,6 +91,15 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }
+    ],
+    "name": "addCollectionAdminSubstrate",
+    "outputs": [],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "user", "type": "address" }
     ],
     "name": "addToAllowList",
@@ -300,6 +309,15 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }
+    ],
+    "name": "removeCollectionAdminSubstrate",
+    "outputs": [],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "user", "type": "address" }
     ],
     "name": "removeFromAllowList",