git.delta.rocks / unique-network / refs/commits / 0dc93c7a2ef6

difftreelog

CORE-302 Fully support create collection from evm

Trubnikov Sergey2022-04-15parent: #ce8ad29.patch.diff
in: master

10 files changed

modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
327 }327 }
328}328}
329329
330#[impl_for_tuples(1, 5)]330#[impl_for_tuples(1, 12)]
331impl SolidityArguments for Tuple {331impl SolidityArguments for Tuple {
332 for_tuples!( where #( Tuple: SolidityArguments ),* );332 for_tuples!( where #( Tuple: SolidityArguments ),* );
333333
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
23 account::CrossAccountId, Pallet as PalletEvm23 account::CrossAccountId, Pallet as PalletEvm
24};24};
25use sp_core::H160;25use sp_core::H160;
26use up_data_structs::{
27 CreateCollectionData, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
28 MAX_COLLECTION_NAME_LENGTH,
29};
26use crate::{30use crate::{
27 AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,31 AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,
28};32};
29use frame_support::traits::Get;33use frame_support::traits::Get;
30use up_sponsorship::SponsorshipHandler;34use up_sponsorship::SponsorshipHandler;
31use sp_std::vec::Vec;35use sp_std::vec::Vec;
36use alloc::format;
3237
33struct ContractHelpers<T: Config>(SubstrateRecorder<T>);38struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
34impl<T: Config> WithRecorder<T> for ContractHelpers<T> {39impl<T: Config> WithRecorder<T> for ContractHelpers<T> {
140145
141 fn create_721_collection(&self, caller: caller) -> Result<address> {146 fn create_721_collection(
147 &self,
148 caller: caller,
149 name: string,
150 description: string,
151 token_prefix: string,
152 ) -> Result<address> {
142 let caller = T::CrossAccountId::from_eth(caller);153 let caller = T::CrossAccountId::from_eth(caller);
154 let name = name
155 .encode_utf16()
156 .collect::<Vec<u16>>()
157 .try_into()
158 .map_err(|_| error_feild_too_long("name", MAX_COLLECTION_NAME_LENGTH))?;
159 let description = description
160 .encode_utf16()
161 .collect::<Vec<u16>>()
162 .try_into()
163 .map_err(|_| error_feild_too_long("description", MAX_COLLECTION_DESCRIPTION_LENGTH))?;
164 let token_prefix = token_prefix
165 .into_bytes()
166 .try_into()
167 .map_err(|_| error_feild_too_long("token_prefix", MAX_TOKEN_PREFIX_LENGTH))?;
168
169 let data = CreateCollectionData {
170 name,
171 description,
172 token_prefix,
173 ..Default::default()
174 };
175
143 let collection_id = <pallet_nonfungible::Pallet<T>>::init_collection(176 let collection_id =
144 caller.as_sub().clone(),177 <pallet_nonfungible::Pallet<T>>::init_collection(caller.as_sub().clone(), data)
145 Default::default(),
146 )
147 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;178 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
179
158 }190 }
159}191}
192
193fn error_feild_too_long(feild: &str, bound: u32) -> Error {
194 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))
195}
160196
161pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);197pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);
162impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T> {198impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T> {
modifiedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
1616
17#![cfg_attr(not(feature = "std"), no_std)]17#![cfg_attr(not(feature = "std"), no_std)]
18
19#[macro_use(format)]
20extern crate alloc;
1821
19use codec::{Decode, Encode, MaxEncodedLen};22use codec::{Decode, Encode, MaxEncodedLen};
20pub use pallet::*;23pub use pallet::*;
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth
21 }21 }
22}22}
2323
24// Selector: e123b7a824// Selector: ee5467a8
25contract ContractHelpers is Dummy, ERC165 {25contract ContractHelpers is Dummy, ERC165 {
26 // Selector: contractOwner(address) 5152b14c26 // Selector: contractOwner(address) 5152b14c
27 function contractOwner(address contractAddress)27 function contractOwner(address contractAddress)
145 dummy = 0;145 dummy = 0;
146 }146 }
147147
148 // Selector: create721Collection() 9a6bd151148 // Selector: create721Collection(string,string,string) 951c0151
149 function create721Collection() public view returns (address) {149 function create721Collection(
150 string memory name,
151 string memory description,
152 string memory tokenPrefix
153 ) public view returns (address) {
150 require(false, stub_error);154 require(false, stub_error);
155 name;
156 description;
157 tokenPrefix;
151 dummy;158 dummy;
152 return 0x0000000000000000000000000000000000000000;159 return 0x0000000000000000000000000000000000000000;
153 }160 }
modifiedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
12 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);
13}13}
1414
15// Selector: e123b7a815// Selector: ee5467a8
16interface ContractHelpers is Dummy, ERC165 {16interface ContractHelpers is Dummy, ERC165 {
17 // Selector: contractOwner(address) 5152b14c17 // Selector: contractOwner(address) 5152b14c
18 function contractOwner(address contractAddress)18 function contractOwner(address contractAddress)
72 bool allowed72 bool allowed
73 ) external;73 ) external;
7474
75 // Selector: create721Collection() 9a6bd15175 // Selector: create721Collection(string,string,string) 951c0151
76 function create721Collection() external view returns (address);76 function create721Collection(
77 string memory name,
78 string memory description,
79 string memory tokenPrefix
80 ) external view returns (address);
77}81}
7882
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
28 usingWeb3,28 usingWeb3,
29} from './util/helpers';29} from './util/helpers';
30import {expect} from 'chai';30import {expect} from 'chai';
31import {createCollectionExpectSuccess, createItemExpectSuccess, getCreatedCollectionCount, UNIQUE} from '../util/helpers';31import {createCollectionExpectSuccess, createItemExpectSuccess, getCreatedCollectionCount, getDetailedCollectionInfo, UNIQUE} from '../util/helpers';
32import nonFungibleAbi from './nonFungibleAbi.json';32import nonFungibleAbi from './nonFungibleAbi.json';
33import privateKey from '../substrate/privateKey';33import privateKey from '../substrate/privateKey';
34import {Contract} from 'web3-eth-contract';34import {Contract} from 'web3-eth-contract';
128describe('Create collection from EVM', () => {128describe('Create collection from EVM', () => {
129 itWeb3('Create collection', async ({api, web3}) => {129 itWeb3('Create collection', async ({api, web3}) => {
130 const owner = await createEthAccountWithBalance(api, web3);130 const owner = await createEthAccountWithBalance(api, web3);
131 console.log(owner);
132 const helpers = contractHelpers(web3, owner);131 const helpers = contractHelpers(web3, owner);
132 const collectionName = 'CollectionEVM';
133 const description = 'Some description';
134 const tokenPrefix = 'token prefix';
135
133 const collectionCountBefore = await getCreatedCollectionCount(api);136 const collectionCountBefore = await getCreatedCollectionCount(api);
134 const result = await helpers.methods.create721Collection().send();137 const result = await helpers.methods
138 .create721Collection(collectionName, description, tokenPrefix)
139 .send();
135 console.log(result.events[0].raw);140 const collectionCountAfter = await getCreatedCollectionCount(api);
141
136 const collectionId = collectionIdFromAddress(result.events[0].raw.topics[2]);142 const collectionId = collectionIdFromAddress(result.events[0].raw.topics[2]);
137 const collectionCountAfter = await getCreatedCollectionCount(api);
138 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);143 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
139 expect(collectionId).to.be.eq(collectionCountAfter);144 expect(collectionId).to.be.eq(collectionCountAfter);
145
146 const collection = (await getDetailedCollectionInfo(api, collectionId))!;
147 expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
148 expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
149 expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
140 });150 });
141});151});
142152
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
1[1[
2 {2 {
3 "anonymous": false,
4 "inputs": [
5 {
6 "indexed": true,
7 "internalType": "address",
8 "name": "owner",
9 "type": "address"
10 },
11 {
12 "indexed": true,
13 "internalType": "address",
14 "name": "spender",
15 "type": "address"
16 },
17 {
18 "indexed": false,
19 "internalType": "uint256",
20 "name": "value",
21 "type": "uint256"
22 }
23 ],
24 "name": "Approval",
25 "type": "event"
26 },
27 {
28 "anonymous": false,
29 "inputs": [
30 {
31 "indexed": true,
32 "internalType": "address",
33 "name": "from",
34 "type": "address"
35 },
36 {
37 "indexed": true,
38 "internalType": "address",
39 "name": "to",
40 "type": "address"
41 },
42 {
43 "indexed": false,
44 "internalType": "uint256",
45 "name": "value",
46 "type": "uint256"
47 }
48 ],
49 "name": "Transfer",
50 "type": "event"
51 },
52 {
53 "inputs": [
54 { "internalType": "address", "name": "owner", "type": "address" },
55 { "internalType": "address", "name": "spender", "type": "address" }
56 ],
57 "name": "allowance",
3 "constant": false,58 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
59 "stateMutability": "view",
60 "type": "function"
61 },
62 {
4 "inputs": [63 "inputs": [
5 {64 { "internalType": "address", "name": "spender", "type": "address" },
6 "name": "_spender",
7 "type": "address"
8 },
9 {65 { "internalType": "uint256", "name": "amount", "type": "uint256" }
10 "name": "_value",
11 "type": "uint256"
12 }
13 ],66 ],
14 "name": "approve",67 "name": "approve",
15 "outputs": [68 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
16 {
17 "name": "",
18 "type": "bool"
19 }
20 ],
21 "payable": false,
22 "stateMutability": "nonpayable",69 "stateMutability": "nonpayable",
23 "type": "function"70 "type": "function"
24 },71 },
25 {72 {
73 "inputs": [
26 "constant": true,74 { "internalType": "address", "name": "owner", "type": "address" }
27 "inputs": [],75 ],
28 "name": "totalSupply",76 "name": "balanceOf",
29 "outputs": [77 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
30 {
31 "name": "",
32 "type": "uint256"
33 }
34 ],
35 "payable": false,
36 "stateMutability": "view",78 "stateMutability": "view",
37 "type": "function"79 "type": "function"
38 },80 },
39 {81 {
40 "constant": false,
41 "inputs": [82 "inputs": [
42 {
43 "name": "_from",
44 "type": "address"83 { "internalType": "address", "name": "from", "type": "address" },
45 },
46 {
47 "name": "_to",
48 "type": "address"
49 },
50 {84 { "internalType": "uint256", "name": "amount", "type": "uint256" }
51 "name": "_value",
52 "type": "uint256"
53 }
54 ],85 ],
55 "name": "transferFrom",86 "name": "burnFrom",
56 "outputs": [87 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
57 {
58 "name": "",
59 "type": "bool"
60 }
61 ],
62 "payable": false,
63 "stateMutability": "nonpayable",88 "stateMutability": "nonpayable",
64 "type": "function"89 "type": "function"
65 },90 },
66 {91 {
67 "constant": true,
68 "inputs": [92 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
69 {
70 "name": "_owner",
71 "type": "address"
72 }
73 ],
74 "name": "balanceOf",93 "name": "collectionProperty",
75 "outputs": [94 "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
76 {
77 "name": "balance",
78 "type": "uint256"
79 }
80 ],
81 "payable": false,
82 "stateMutability": "view",95 "stateMutability": "view",
83 "type": "function"96 "type": "function"
84 },97 },
85 {98 {
86 "constant": false,99 "inputs": [],
87 "inputs": [100 "name": "decimals",
88 {
89 "name": "_to",101 "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
102 "stateMutability": "view",
90 "type": "address"103 "type": "function"
91 },104 },
92 {105 {
93 "name": "_value",106 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
107 "name": "deleteCollectionProperty",
108 "outputs": [],
109 "stateMutability": "nonpayable",
94 "type": "uint256"110 "type": "function"
95 }111 },
112 {
96 ],113 "inputs": [],
97 "name": "transfer",114 "name": "name",
98 "outputs": [115 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
99 {
100 "name": "",
101 "type": "bool"
102 }
103 ],
104 "payable": false,116 "stateMutability": "view",
105 "stateMutability": "nonpayable",117 "type": "function"
118 },
119 {
120 "inputs": [
106 "type": "function"121 { "internalType": "string", "name": "key", "type": "string" },
107 },
108 {122 { "internalType": "bytes", "name": "value", "type": "bytes" }
109 "constant": true,123 ],
110 "inputs": [
111 {
112 "name": "_owner",124 "name": "setCollectionProperty",
125 "outputs": [],
126 "stateMutability": "nonpayable",
113 "type": "address"127 "type": "function"
114 },128 },
129 {
130 "inputs": [
115 {131 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
116 "name": "_spender",
117 "type": "address"
118 }
119 ],132 ],
120 "name": "allowance",133 "name": "supportsInterface",
121 "outputs": [134 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
122 {135 "stateMutability": "view",
123 "name": "",
124 "type": "uint256"
125 }
126 ],
127 "payable": false,136 "type": "function"
137 },
138 {
139 "inputs": [],
140 "name": "symbol",
141 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
128 "stateMutability": "view",142 "stateMutability": "view",
129 "type": "function"143 "type": "function"
130 },144 },
131 {145 {
132 "anonymous": false,146 "inputs": [],
147 "name": "totalSupply",
133 "inputs": [148 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
134 {149 "stateMutability": "view",
135 "indexed": true,
136 "name": "owner",
137 "type": "address"150 "type": "function"
138 },151 },
152 {
153 "inputs": [
139 {154 { "internalType": "address", "name": "to", "type": "address" },
140 "indexed": true,
141 "name": "spender",
142 "type": "address"
143 },
144 {155 { "internalType": "uint256", "name": "amount", "type": "uint256" }
145 "indexed": false,
146 "name": "value",
147 "type": "uint256"
148 }
149 ],156 ],
150 "name": "Approval",157 "name": "transfer",
151 "type": "event"158 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
152 },159 "stateMutability": "nonpayable",
153 {
154 "anonymous": false,160 "type": "function"
161 },
162 {
155 "inputs": [163 "inputs": [
156 {164 { "internalType": "address", "name": "from", "type": "address" },
157 "indexed": true,
158 "name": "from",
159 "type": "address"
160 },
161 {165 { "internalType": "address", "name": "to", "type": "address" },
162 "indexed": true,
163 "name": "to",
164 "type": "address"
165 },
166 {166 { "internalType": "uint256", "name": "amount", "type": "uint256" }
167 "indexed": false,
168 "name": "value",
169 "type": "uint256"
170 }
171 ],167 ],
172 "name": "Transfer",168 "name": "transferFrom",
169 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
170 "stateMutability": "nonpayable",
173 "type": "event"171 "type": "function"
174 }172 }
175]173]
174
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth

no syntactic changes

modifiedtests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth
63 },41 },
64 {42 {
65 "inputs": [],43 "inputs": [
44 { "internalType": "string", "name": "name", "type": "string" },
45 { "internalType": "string", "name": "description", "type": "string" },
46 { "internalType": "string", "name": "tokenPrefix", "type": "string" }
47 ],
66 "name": "create721Collection",48 "name": "create721Collection",
67 "outputs": [49 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],