difftreelog
CORE-302 Implement setSponsor method.
in: master
10 files changed
Makefilediffbeforeafterboth21TESTS_API=./tests/src/eth/api/21TESTS_API=./tests/src/eth/api/222223.PHONY: regenerate_solidity23.PHONY: regenerate_solidity24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol Collection.sol252526UniqueFungible.sol:26UniqueFungible.sol:27 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh27 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh36 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh36 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=$(CONTRACT_HELPERS_STUBS)/$@ ./.maintain/scripts/generate_sol.sh373738Collection.sol:38Collection.sol:39 PACKAGE=pallet-evm-collection NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh39 PACKAGE=pallet-evm-collection NAME=eth::collection_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh40 PACKAGE=pallet-evm-collection NAME=eth::contract_helpers_impl OUTPUT=$(COLLECTION_STUBS)/$@ ./.maintain/scripts/generate_sol.sh40 PACKAGE=pallet-evm-collection NAME=eth::collection_impl OUTPUT=$(COLLECTION_STUBS)/$@ ./.maintain/scripts/generate_sol.sh414142UniqueFungible: UniqueFungible.sol42UniqueFungible: UniqueFungible.sol43 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw ./.maintain/scripts/compile_stub.sh43 INPUT=$(FUNGIBLE_EVM_STUBS)/$< OUTPUT=$(FUNGIBLE_EVM_STUBS)/UniqueFungible.raw ./.maintain/scripts/compile_stub.shpallets/common/src/lib.rsdiffbeforeafterboth115 })115 })116 }116 }117118 pub fn new_with_recorder(id: CollectionId, recorder: Rc<SubstrateRecorder<T>>) -> Option<Self> {119 <CollectionById<T>>::get(id).map(|collection| Self {120 id,121 collection,122 recorder,123 })124 }125117 pub fn new(id: CollectionId) -> Option<Self> {126 pub fn new(id: CollectionId) -> Option<Self> {118 Self::new_with_gas_limit(id, u64::MAX)127 Self::new_with_gas_limit(id, u64::MAX)141 Ok(())150 Ok(())142 }151 }152153 pub fn set_sponsor(&mut self, sponsor: T::AccountId) {154 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);155 }143}156}144impl<T: Config> Deref for CollectionHandle<T> {157impl<T: Config> Deref for CollectionHandle<T> {145 type Target = Collection<T::AccountId>;158 type Target = Collection<T::AccountId>;pallets/evm-collection/src/eth.rsdiffbeforeafterboth17use core::marker::PhantomData;17use core::marker::PhantomData;18use evm_coder::{abi::AbiWriter, execution::*, generate_stubgen, solidity_interface, types::*, ToLog};18use evm_coder::{abi::AbiWriter, execution::*, generate_stubgen, solidity_interface, types::*, ToLog};19use ethereum as _;19use ethereum as _;20use pallet_common::CollectionById;20use pallet_common::{CollectionById, CollectionHandle};21use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};21use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};22use pallet_evm::{22use pallet_evm::{23 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure,23 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure,26use sp_core::H160;26use sp_core::H160;27use up_data_structs::{27use up_data_structs::{28 CreateCollectionData, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,28 CreateCollectionData, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,29 MAX_COLLECTION_NAME_LENGTH,29 MAX_COLLECTION_NAME_LENGTH, SponsorshipState,30};30};31use crate::{Config, Pallet};31use crate::{Config, Pallet};32use frame_support::traits::Get;32use frame_support::traits::Get;102 Ok(address)103 Ok(address)103 }104 }104105105 // fn set_sponsor(collection_id: address, sponsor: address) -> Result<void> {106 fn set_sponsor(106 // let collection_id =107 &self,107 // pallet_common::eth::map_eth_to_id(&collection_id).ok_or(Error::Revert("".into()))?;108 caller: caller,108 // let mut collection = <CollectionById<T>>::get(collection_id).ok_or(Error::Revert("".into()))?;109 contract_address: address,109 // let sponsor = T::CrossAccountId::from_eth(sponsor);110 sponsor: address,110 // collection.sponsorship = SponsorshipState::Unconfirmed(sponsor.as_sub().clone());111 ) -> Result<void> {111 // <CollectionById<T>>::insert(collection_id, collection);112 let collection_id =112 // Ok(())113 pallet_common::eth::map_eth_to_id(&contract_address).ok_or(Error::Revert("".into()))?;113 // }114 let mut collection =115 pallet_common::CollectionHandle::new_with_recorder(collection_id, self.0.clone())116 .ok_or(Error::Revert("".into()))?;117 118 let caller = T::CrossAccountId::from_eth(caller);119 collection.check_is_owner(&caller).map_err(|e| Error::Revert(format!("{:?}", e)))?;120121 let sponsor = T::CrossAccountId::from_eth(sponsor);122 collection.set_sponsor(sponsor.as_sub().clone());123 collection124 .save()125 .map_err(|e| Error::Revert(format!("{:?}", e)))126 }114127115 // fn set_offchain_shema(shema: string) -> Result<void> {128 // fn set_offchain_shema(shema: string) -> Result<void> {116 // Ok(())129 // Ok(())pallets/evm-collection/src/stubs/Collection.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-collection/src/stubs/Collection.soldiffbeforeafterboth21 }21 }22}22}232324// Selector: ee5467a824// Selector: 6503bbc225contract Collection is Dummy, ERC165 {25contract Collection is Dummy, ERC165 {26 // Selector: contractOwner(address) 5152b14c26 // Selector: create721Collection(string,string,string) 951c015127 function contractOwner(address contractAddress)28 public29 view30 returns (address)31 {32 require(false, stub_error);33 contractAddress;34 dummy;35 return 0x0000000000000000000000000000000000000000;36 }3738 // Selector: sponsoringEnabled(address) 6027dc6139 function sponsoringEnabled(address contractAddress)27 function create721Collection(40 public41 view42 returns (bool)43 {44 require(false, stub_error);28 string memory name,45 contractAddress;46 dummy;47 return false;48 }4950 // Deprecated51 //52 // Selector: toggleSponsoring(address,bool) fcac6d8653 function toggleSponsoring(address contractAddress, bool enabled) public {29 string memory description,54 require(false, stub_error);30 string memory tokenPrefix55 contractAddress;56 enabled;57 dummy = 0;58 }5960 // Selector: setSponsoringMode(address,uint8) fde8a56061 function setSponsoringMode(address contractAddress, uint8 mode) public {62 require(false, stub_error);63 contractAddress;64 mode;65 dummy = 0;66 }6768 // Selector: sponsoringMode(address) b70c726769 function sponsoringMode(address contractAddress)70 public71 view31 ) public view returns (address) {72 returns (uint8)73 {74 require(false, stub_error);75 contractAddress;76 dummy;77 return 0;78 }7980 // Selector: setSponsoringRateLimit(address,uint32) 77b6c90881 function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)82 public83 {84 require(false, stub_error);32 require(false, stub_error);85 contractAddress;33 name;86 rateLimit;34 description;87 dummy = 0;88 }8990 // Selector: getSponsoringRateLimit(address) 610cfabd91 function getSponsoringRateLimit(address contractAddress)92 public93 view94 returns (uint32)95 {96 require(false, stub_error);35 tokenPrefix;97 contractAddress;98 dummy;36 dummy;99 return 0;37 return 0x0000000000000000000000000000000000000000;100 }38 }10139102 // Selector: allowed(address,address) 5c65816540 // Selector: setSponsor(address,address) f01fba93103 function allowed(address contractAddress, address user)41 function setSponsor(address contractAddress, address sponsor) public view {104 public105 view106 returns (bool)107 {108 require(false, stub_error);42 require(false, stub_error);109 contractAddress;43 contractAddress;110 user;44 sponsor;111 dummy;45 dummy;112 return false;113 }46 }114115 // Selector: allowlistEnabled(address) c772ef6c116 function allowlistEnabled(address contractAddress)117 public118 view119 returns (bool)120 {121 require(false, stub_error);122 contractAddress;123 dummy;124 return false;125 }126127 // Selector: toggleAllowlist(address,bool) 36de20f5128 function toggleAllowlist(address contractAddress, bool enabled) public {129 require(false, stub_error);130 contractAddress;131 enabled;132 dummy = 0;133 }134135 // Selector: toggleAllowed(address,address,bool) 4706cc1c136 function toggleAllowed(137 address contractAddress,138 address user,139 bool allowed140 ) public {141 require(false, stub_error);142 contractAddress;143 user;144 allowed;145 dummy = 0;146 }147148 // Selector: create721Collection(string,string,string) 951c0151149 function create721Collection(150 string memory name,151 string memory description,152 string memory tokenPrefix153 ) public view returns (address) {154 require(false, stub_error);155 name;156 description;157 tokenPrefix;158 dummy;159 return 0x0000000000000000000000000000000000000000;160 }161}47}16248pallets/unique/src/lib.rsdiffbeforeafterboth520 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;520 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;521 target_collection.check_is_owner(&sender)?;521 target_collection.check_is_owner(&sender)?;522522523 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor.clone());523 target_collection.set_sponsor(new_sponsor.clone());524524525 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(525 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(526 collection_id,526 collection_id,tests/src/eth/api/Collection.soldiffbeforeafterboth12 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}13}141415// Selector: ee5467a815// Selector: 6503bbc216interface Collection is Dummy, ERC165 {16interface Collection is Dummy, ERC165 {17 // Selector: contractOwner(address) 5152b14c18 function contractOwner(address contractAddress)19 external20 view21 returns (address);2223 // Selector: sponsoringEnabled(address) 6027dc6124 function sponsoringEnabled(address contractAddress)25 external26 view27 returns (bool);2829 // Deprecated30 //31 // Selector: toggleSponsoring(address,bool) fcac6d8632 function toggleSponsoring(address contractAddress, bool enabled) external;3334 // Selector: setSponsoringMode(address,uint8) fde8a56035 function setSponsoringMode(address contractAddress, uint8 mode) external;3637 // Selector: sponsoringMode(address) b70c726738 function sponsoringMode(address contractAddress)39 external40 view41 returns (uint8);4243 // Selector: setSponsoringRateLimit(address,uint32) 77b6c90844 function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)45 external;4647 // Selector: getSponsoringRateLimit(address) 610cfabd48 function getSponsoringRateLimit(address contractAddress)49 external50 view51 returns (uint32);5253 // Selector: allowed(address,address) 5c65816554 function allowed(address contractAddress, address user)55 external56 view57 returns (bool);5859 // Selector: allowlistEnabled(address) c772ef6c60 function allowlistEnabled(address contractAddress)61 external62 view63 returns (bool);6465 // Selector: toggleAllowlist(address,bool) 36de20f566 function toggleAllowlist(address contractAddress, bool enabled) external;6768 // Selector: toggleAllowed(address,address,bool) 4706cc1c69 function toggleAllowed(70 address contractAddress,71 address user,72 bool allowed73 ) external;7475 // Selector: create721Collection(string,string,string) 951c015117 // Selector: create721Collection(string,string,string) 951c015176 function create721Collection(18 function create721Collection(79 string memory tokenPrefix21 string memory tokenPrefix80 ) external view returns (address);22 ) external view returns (address);2324 // Selector: setSponsor(address,address) f01fba9325 function setSponsor(address contractAddress, address sponsor) external view;81}26}8227tests/src/eth/collectionAbi.jsondiffbeforeafterboth1[1[2 {3 "inputs": [4 {5 "internalType": "address",6 "name": "contractAddress",7 "type": "address"8 },9 { "internalType": "address", "name": "user", "type": "address" }10 ],11 "name": "allowed",12 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],13 "stateMutability": "view",14 "type": "function"15 },16 {17 "inputs": [18 {19 "internalType": "address",20 "name": "contractAddress",21 "type": "address"22 }23 ],24 "name": "allowlistEnabled",25 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],26 "stateMutability": "view",27 "type": "function"28 },29 {30 "inputs": [31 {32 "internalType": "address",33 "name": "contractAddress",34 "type": "address"35 }36 ],37 "name": "contractOwner",38 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],39 "stateMutability": "view",40 "type": "function"41 },42 {2 {43 "inputs": [3 "inputs": [44 { "internalType": "string", "name": "name", "type": "string" },4 { "internalType": "string", "name": "name", "type": "string" },50 "stateMutability": "view",10 "stateMutability": "view",51 "type": "function"11 "type": "function"52 },12 },53 {13 {54 "inputs": [55 {56 "internalType": "address",57 "name": "contractAddress",58 "type": "address"59 }60 ],61 "name": "getSponsoringRateLimit",62 "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }],63 "stateMutability": "view",64 "type": "function"65 },66 {67 "inputs": [14 "inputs": [68 {15 {69 "internalType": "address",16 "internalType": "address",70 "name": "contractAddress",17 "name": "contractAddress",71 "type": "address"18 "type": "address"72 },19 },73 { "internalType": "uint8", "name": "mode", "type": "uint8" }20 { "internalType": "address", "name": "sponsor", "type": "address" }74 ],21 ],75 "name": "setSponsoringMode",22 "name": "setSponsor",76 "outputs": [],23 "outputs": [],77 "stateMutability": "nonpayable",78 "type": "function"79 },80 {81 "inputs": [82 {83 "internalType": "address",84 "name": "contractAddress",85 "type": "address"86 },87 { "internalType": "uint32", "name": "rateLimit", "type": "uint32" }88 ],89 "name": "setSponsoringRateLimit",90 "outputs": [],91 "stateMutability": "nonpayable",92 "type": "function"93 },94 {95 "inputs": [96 {97 "internalType": "address",98 "name": "contractAddress",99 "type": "address"100 }101 ],102 "name": "sponsoringEnabled",103 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],104 "stateMutability": "view",24 "stateMutability": "view",105 "type": "function"25 "type": "function"106 },26 },107 {108 "inputs": [109 {110 "internalType": "address",111 "name": "contractAddress",112 "type": "address"113 }114 ],115 "name": "sponsoringMode",116 "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],117 "stateMutability": "view",118 "type": "function"119 },120 {27 {121 "inputs": [28 "inputs": [122 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }29 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }125 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],32 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],126 "stateMutability": "view",33 "stateMutability": "view",127 "type": "function"34 "type": "function"128 },35 }129 {130 "inputs": [131 {132 "internalType": "address",133 "name": "contractAddress",134 "type": "address"135 },136 { "internalType": "address", "name": "user", "type": "address" },137 { "internalType": "bool", "name": "allowed", "type": "bool" }138 ],139 "name": "toggleAllowed",140 "outputs": [],141 "stateMutability": "nonpayable",142 "type": "function"143 },144 {145 "inputs": [146 {147 "internalType": "address",148 "name": "contractAddress",149 "type": "address"150 },151 { "internalType": "bool", "name": "enabled", "type": "bool" }152 ],153 "name": "toggleAllowlist",154 "outputs": [],155 "stateMutability": "nonpayable",156 "type": "function"157 },158 {159 "inputs": [160 {161 "internalType": "address",162 "name": "contractAddress",163 "type": "address"164 },165 { "internalType": "bool", "name": "enabled", "type": "bool" }166 ],167 "name": "toggleSponsoring",168 "outputs": [],169 "stateMutability": "nonpayable",170 "type": "function"171 }172]36]17337tests/src/eth/createCollection.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {ApiPromise} from '@polkadot/api';18import {evmToAddress} from '@polkadot/util-crypto';17import {expect} from 'chai';19import {expect} from 'chai';18import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';20import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';19import {collectionHelper, collectionIdFromAddress, contractHelpers, createEthAccountWithBalance, itWeb3} from './util/helpers';21import {collectionHelper, collectionIdFromAddress, createEthAccountWithBalance, itWeb3, normalizeAddress} from './util/helpers';2223async function getCollectionAddressFromResult(api: ApiPromise, result: any) {24 const collectionIdAddress = normalizeAddress(result.events[0].raw.topics[2]);25 const collectionId = collectionIdFromAddress(collectionIdAddress); 26 const collection = (await getDetailedCollectionInfo(api, collectionId))!;27 return {collectionIdAddress, collectionId, collection};28}202921describe('Create collection from EVM', () => {30describe('Create collection from EVM', () => {22 itWeb3('Create collection', async ({api, web3}) => {31 itWeb3('Create collection', async ({api, web3}) => {23 const owner = await createEthAccountWithBalance(api, web3);32 const owner = await createEthAccountWithBalance(api, web3);24 const helpers = collectionHelper(web3, owner);33 const helper = collectionHelper(web3, owner);25 const collectionName = 'CollectionEVM';34 const collectionName = 'CollectionEVM';26 const description = 'Some description';35 const description = 'Some description';27 const tokenPrefix = 'token prefix';36 const tokenPrefix = 'token prefix';28 37 29 const collectionCountBefore = await getCreatedCollectionCount(api);38 const collectionCountBefore = await getCreatedCollectionCount(api);30 const result = await helpers.methods39 const result = await helper.methods31 .create721Collection(collectionName, description, tokenPrefix)40 .create721Collection(collectionName, description, tokenPrefix)32 .send();41 .send();33 const collectionCountAfter = await getCreatedCollectionCount(api);42 const collectionCountAfter = await getCreatedCollectionCount(api);34 43 35 const collectionId = collectionIdFromAddress(result.events[0].raw.topics[2]);44 const {collectionId, collection} = await getCollectionAddressFromResult(api, result);36 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);45 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);37 expect(collectionId).to.be.eq(collectionCountAfter);46 expect(collectionId).to.be.eq(collectionCountAfter);38 39 const collection = (await getDetailedCollectionInfo(api, collectionId))!;40 expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);47 expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);41 expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);48 expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);42 expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);49 expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);43 expect(collection.schemaVersion.type).to.be.eq('ImageURL');50 expect(collection.schemaVersion.type).to.be.eq('ImageURL');44 });51 });52 53 itWeb3('Set sponsorship', async ({api, web3}) => {54 const owner = await createEthAccountWithBalance(api, web3);55 const helper = collectionHelper(web3, owner);56 let result = await helper.methods.create721Collection('Sponsor collection', '1', '1').send();57 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);58 const sponsor = await createEthAccountWithBalance(api, web3);59 result = await helper.methods.setSponsor(collectionIdAddress, sponsor).send();60 const collection = (await getDetailedCollectionInfo(api, collectionId))!;61 expect(collection.sponsorship.isUnconfirmed).to.be.true;62 expect(collection.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));63 });646545});66});tests/src/eth/util/helpers.tsdiffbeforeafterboth74 return Web3.utils.toChecksumAddress('0x' + buf.toString('hex'));74 return Web3.utils.toChecksumAddress('0x' + buf.toString('hex'));75}75}76export function collectionIdFromAddress(address: string): number {76export function collectionIdFromAddress(address: string): number {77 if (!address.startsWith('0x'))78 throw 'address not starts with "0x"';79 if (address.length > 42)80 throw 'address length is more than 20 bytes';77 return Number('0x' + address.substring(address.length - 8));81 return Number('0x' + address.substring(address.length - 8));78}82}83 84export function normalizeAddress(address: string): string {85 return '0x' + address.substring(address.length - 40);86}798780export function tokenIdToAddress(collection: number, token: number): string {88export function tokenIdToAddress(collection: number, token: number): string {81 const buf = Buffer.from([0xf8, 0x23, 0x8c, 0xcf, 0xff, 0x8e, 0xd8, 0x87, 0x46, 0x3f, 0xd5, 0xe0,89 const buf = Buffer.from([0xf8, 0x23, 0x8c, 0xcf, 0xff, 0x8e, 0xd8, 0x87, 0x46, 0x3f, 0xd5, 0xe0,