difftreelog
feature/mint-for-fungible-token
in: master
5 files changed
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -129,7 +129,23 @@
}
}
-#[solidity_interface(name = ERC20UniqueExtensions)]
+#[solidity_interface(name = "ERC20Mintable")]
+impl<T: Config> FungibleHandle<T> {
+ #[weight(<SelfWeightOf<T>>::create_item())]
+ fn mint(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = T::CrossAccountId::from_eth(to);
+ let amount = amount.try_into().map_err(|_| "amount overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+ <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(true)
+ }
+}
+
+#[solidity_interface(name = "ERC20UniqueExtensions")]
impl<T: Config> FungibleHandle<T> {
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {
@@ -144,12 +160,29 @@
.map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
+
+ #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]
+ fn mint_bulk(&mut self, caller: caller, amounts: Vec<(address, uint256)>) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+ let amounts = amounts
+ .into_iter()
+ .map(|(to, amount)| Ok((T::CrossAccountId::from_eth(to), amount.try_into().map_err(|_| "amount overflow")?)))
+ .collect::<Result<_>>()?;
+
+ <Pallet<T>>::create_multiple_items(&self, &caller, amounts, &budget)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(true)
+ }
}
#[solidity_interface(
name = UniqueFungible,
is(
ERC20,
+ ERC20Mintable,
ERC20UniqueExtensions,
Collection(common_mut, CollectionHandle<T>),
)
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56/// @dev common stubs holder7contract Dummy {8 uint8 dummy;9 string stub_error = "this contract is implemented in native";10}1112contract ERC165 is Dummy {13 function supportsInterface(bytes4 interfaceID)14 external15 view16 returns (bool)17 {18 require(false, stub_error);19 interfaceID;20 return true;21 }22}2324/// @title A contract that allows you to work with collections.25/// @dev the ERC-165 identifier for this interface is 0xe54be64026contract Collection is Dummy, ERC165 {27 /// Set collection property.28 ///29 /// @param key Property key.30 /// @param value Propery value.31 /// @dev EVM selector for this function is: 0x2f073f66,32 /// or in textual repr: setCollectionProperty(string,bytes)33 function setCollectionProperty(string memory key, bytes memory value)34 public35 {36 require(false, stub_error);37 key;38 value;39 dummy = 0;40 }4142 /// Delete collection property.43 ///44 /// @param key Property key.45 /// @dev EVM selector for this function is: 0x7b7debce,46 /// or in textual repr: deleteCollectionProperty(string)47 function deleteCollectionProperty(string memory key) public {48 require(false, stub_error);49 key;50 dummy = 0;51 }5253 /// Get collection property.54 ///55 /// @dev Throws error if key not found.56 ///57 /// @param key Property key.58 /// @return bytes The property corresponding to the key.59 /// @dev EVM selector for this function is: 0xcf24fd6d,60 /// or in textual repr: collectionProperty(string)61 function collectionProperty(string memory key)62 public63 view64 returns (bytes memory)65 {66 require(false, stub_error);67 key;68 dummy;69 return hex"";70 }7172 /// Set the sponsor of the collection.73 ///74 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.75 ///76 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.77 /// @dev EVM selector for this function is: 0x7623402e,78 /// or in textual repr: setCollectionSponsor(address)79 function setCollectionSponsor(address sponsor) public {80 require(false, stub_error);81 sponsor;82 dummy = 0;83 }8485 /// Set the substrate sponsor of the collection.86 ///87 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.88 ///89 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.90 /// @dev EVM selector for this function is: 0xc74d6751,91 /// or in textual repr: setCollectionSponsorSubstrate(uint256)92 function setCollectionSponsorSubstrate(uint256 sponsor) public {93 require(false, stub_error);94 sponsor;95 dummy = 0;96 }9798 /// @dev EVM selector for this function is: 0x058ac185,99 /// or in textual repr: hasCollectionPendingSponsor()100 function hasCollectionPendingSponsor() public view returns (bool) {101 require(false, stub_error);102 dummy;103 return false;104 }105106 /// Collection sponsorship confirmation.107 ///108 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.109 /// @dev EVM selector for this function is: 0x3c50e97a,110 /// or in textual repr: confirmCollectionSponsorship()111 function confirmCollectionSponsorship() public {112 require(false, stub_error);113 dummy = 0;114 }115116 /// Remove collection sponsor.117 /// @dev EVM selector for this function is: 0x6e0326a3,118 /// or in textual repr: removeCollectionSponsor()119 function removeCollectionSponsor() public {120 require(false, stub_error);121 dummy = 0;122 }123124 /// Get current sponsor.125 ///126 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.127 /// @dev EVM selector for this function is: 0xb66bbc14,128 /// or in textual repr: getCollectionSponsor()129 function getCollectionSponsor() public view returns (Tuple6 memory) {130 require(false, stub_error);131 dummy;132 return Tuple6(0x0000000000000000000000000000000000000000, 0);133 }134135 /// Set limits for the collection.136 /// @dev Throws error if limit not found.137 /// @param limit Name of the limit. Valid names:138 /// "accountTokenOwnershipLimit",139 /// "sponsoredDataSize",140 /// "sponsoredDataRateLimit",141 /// "tokenLimit",142 /// "sponsorTransferTimeout",143 /// "sponsorApproveTimeout"144 /// @param value Value of the limit.145 /// @dev EVM selector for this function is: 0x6a3841db,146 /// or in textual repr: setCollectionLimit(string,uint32)147 function setCollectionLimit(string memory limit, uint32 value) public {148 require(false, stub_error);149 limit;150 value;151 dummy = 0;152 }153154 /// Set limits for the collection.155 /// @dev Throws error if limit not found.156 /// @param limit Name of the limit. Valid names:157 /// "ownerCanTransfer",158 /// "ownerCanDestroy",159 /// "transfersEnabled"160 /// @param value Value of the limit.161 /// @dev EVM selector for this function is: 0x993b7fba,162 /// or in textual repr: setCollectionLimit(string,bool)163 function setCollectionLimit(string memory limit, bool value) public {164 require(false, stub_error);165 limit;166 value;167 dummy = 0;168 }169170 /// Get contract address.171 /// @dev EVM selector for this function is: 0xf6b4dfb4,172 /// or in textual repr: contractAddress()173 function contractAddress() public view returns (address) {174 require(false, stub_error);175 dummy;176 return 0x0000000000000000000000000000000000000000;177 }178179 /// Add collection admin by substrate address.180 /// @param newAdmin Substrate administrator address.181 /// @dev EVM selector for this function is: 0x5730062b,182 /// or in textual repr: addCollectionAdminSubstrate(uint256)183 function addCollectionAdminSubstrate(uint256 newAdmin) public {184 require(false, stub_error);185 newAdmin;186 dummy = 0;187 }188189 /// Remove collection admin by substrate address.190 /// @param admin Substrate administrator address.191 /// @dev EVM selector for this function is: 0x4048fcf9,192 /// or in textual repr: removeCollectionAdminSubstrate(uint256)193 function removeCollectionAdminSubstrate(uint256 admin) public {194 require(false, stub_error);195 admin;196 dummy = 0;197 }198199 /// Add collection admin.200 /// @param newAdmin Address of the added administrator.201 /// @dev EVM selector for this function is: 0x92e462c7,202 /// or in textual repr: addCollectionAdmin(address)203 function addCollectionAdmin(address newAdmin) public {204 require(false, stub_error);205 newAdmin;206 dummy = 0;207 }208209 /// Remove collection admin.210 ///211 /// @param admin Address of the removed administrator.212 /// @dev EVM selector for this function is: 0xfafd7b42,213 /// or in textual repr: removeCollectionAdmin(address)214 function removeCollectionAdmin(address admin) public {215 require(false, stub_error);216 admin;217 dummy = 0;218 }219220 /// Toggle accessibility of collection nesting.221 ///222 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'223 /// @dev EVM selector for this function is: 0x112d4586,224 /// or in textual repr: setCollectionNesting(bool)225 function setCollectionNesting(bool enable) public {226 require(false, stub_error);227 enable;228 dummy = 0;229 }230231 /// Toggle accessibility of collection nesting.232 ///233 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'234 /// @param collections Addresses of collections that will be available for nesting.235 /// @dev EVM selector for this function is: 0x64872396,236 /// or in textual repr: setCollectionNesting(bool,address[])237 function setCollectionNesting(bool enable, address[] memory collections)238 public239 {240 require(false, stub_error);241 enable;242 collections;243 dummy = 0;244 }245246 /// Set the collection access method.247 /// @param mode Access mode248 /// 0 for Normal249 /// 1 for AllowList250 /// @dev EVM selector for this function is: 0x41835d4c,251 /// or in textual repr: setCollectionAccess(uint8)252 function setCollectionAccess(uint8 mode) public {253 require(false, stub_error);254 mode;255 dummy = 0;256 }257258 /// Add the user to the allowed list.259 ///260 /// @param user Address of a trusted user.261 /// @dev EVM selector for this function is: 0x67844fe6,262 /// or in textual repr: addToCollectionAllowList(address)263 function addToCollectionAllowList(address user) public {264 require(false, stub_error);265 user;266 dummy = 0;267 }268269 /// Remove the user from the allowed list.270 ///271 /// @param user Address of a removed user.272 /// @dev EVM selector for this function is: 0x85c51acb,273 /// or in textual repr: removeFromCollectionAllowList(address)274 function removeFromCollectionAllowList(address user) public {275 require(false, stub_error);276 user;277 dummy = 0;278 }279280 /// Switch permission for minting.281 ///282 /// @param mode Enable if "true".283 /// @dev EVM selector for this function is: 0x00018e84,284 /// or in textual repr: setCollectionMintMode(bool)285 function setCollectionMintMode(bool mode) public {286 require(false, stub_error);287 mode;288 dummy = 0;289 }290291 /// Check that account is the owner or admin of the collection292 ///293 /// @param user account to verify294 /// @return "true" if account is the owner or admin295 /// @dev EVM selector for this function is: 0x9811b0c7,296 /// or in textual repr: isOwnerOrAdmin(address)297 function isOwnerOrAdmin(address user) public view returns (bool) {298 require(false, stub_error);299 user;300 dummy;301 return false;302 }303304 /// Check that substrate account is the owner or admin of the collection305 ///306 /// @param user account to verify307 /// @return "true" if account is the owner or admin308 /// @dev EVM selector for this function is: 0x68910e00,309 /// or in textual repr: isOwnerOrAdminSubstrate(uint256)310 function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {311 require(false, stub_error);312 user;313 dummy;314 return false;315 }316317 /// Returns collection type318 ///319 /// @return `Fungible` or `NFT` or `ReFungible`320 /// @dev EVM selector for this function is: 0xd34b55b8,321 /// or in textual repr: uniqueCollectionType()322 function uniqueCollectionType() public returns (string memory) {323 require(false, stub_error);324 dummy = 0;325 return "";326 }327328 /// Changes collection owner to another account329 ///330 /// @dev Owner can be changed only by current owner331 /// @param newOwner new owner account332 /// @dev EVM selector for this function is: 0x13af4035,333 /// or in textual repr: setOwner(address)334 function setOwner(address newOwner) public {335 require(false, stub_error);336 newOwner;337 dummy = 0;338 }339340 /// Changes collection owner to another substrate account341 ///342 /// @dev Owner can be changed only by current owner343 /// @param newOwner new owner substrate account344 /// @dev EVM selector for this function is: 0xb212138f,345 /// or in textual repr: setOwnerSubstrate(uint256)346 function setOwnerSubstrate(uint256 newOwner) public {347 require(false, stub_error);348 newOwner;349 dummy = 0;350 }351}352353/// @dev anonymous struct354struct Tuple6 {355 address field_0;356 uint256 field_1;357}358359/// @dev the ERC-165 identifier for this interface is 0x79cc6790360contract ERC20UniqueExtensions is Dummy, ERC165 {361 /// @dev EVM selector for this function is: 0x79cc6790,362 /// or in textual repr: burnFrom(address,uint256)363 function burnFrom(address from, uint256 amount) public returns (bool) {364 require(false, stub_error);365 from;366 amount;367 dummy = 0;368 return false;369 }370}371372/// @dev inlined interface373contract ERC20Events {374 event Transfer(address indexed from, address indexed to, uint256 value);375 event Approval(376 address indexed owner,377 address indexed spender,378 uint256 value379 );380}381382/// @dev the ERC-165 identifier for this interface is 0x942e8b22383contract ERC20 is Dummy, ERC165, ERC20Events {384 /// @dev EVM selector for this function is: 0x06fdde03,385 /// or in textual repr: name()386 function name() public view returns (string memory) {387 require(false, stub_error);388 dummy;389 return "";390 }391392 /// @dev EVM selector for this function is: 0x95d89b41,393 /// or in textual repr: symbol()394 function symbol() public view returns (string memory) {395 require(false, stub_error);396 dummy;397 return "";398 }399400 /// @dev EVM selector for this function is: 0x18160ddd,401 /// or in textual repr: totalSupply()402 function totalSupply() public view returns (uint256) {403 require(false, stub_error);404 dummy;405 return 0;406 }407408 /// @dev EVM selector for this function is: 0x313ce567,409 /// or in textual repr: decimals()410 function decimals() public view returns (uint8) {411 require(false, stub_error);412 dummy;413 return 0;414 }415416 /// @dev EVM selector for this function is: 0x70a08231,417 /// or in textual repr: balanceOf(address)418 function balanceOf(address owner) public view returns (uint256) {419 require(false, stub_error);420 owner;421 dummy;422 return 0;423 }424425 /// @dev EVM selector for this function is: 0xa9059cbb,426 /// or in textual repr: transfer(address,uint256)427 function transfer(address to, uint256 amount) public returns (bool) {428 require(false, stub_error);429 to;430 amount;431 dummy = 0;432 return false;433 }434435 /// @dev EVM selector for this function is: 0x23b872dd,436 /// or in textual repr: transferFrom(address,address,uint256)437 function transferFrom(438 address from,439 address to,440 uint256 amount441 ) public returns (bool) {442 require(false, stub_error);443 from;444 to;445 amount;446 dummy = 0;447 return false;448 }449450 /// @dev EVM selector for this function is: 0x095ea7b3,451 /// or in textual repr: approve(address,uint256)452 function approve(address spender, uint256 amount) public returns (bool) {453 require(false, stub_error);454 spender;455 amount;456 dummy = 0;457 return false;458 }459460 /// @dev EVM selector for this function is: 0xdd62ed3e,461 /// or in textual repr: allowance(address,address)462 function allowance(address owner, address spender)463 public464 view465 returns (uint256)466 {467 require(false, stub_error);468 owner;469 spender;470 dummy;471 return 0;472 }473}474475contract UniqueFungible is476 Dummy,477 ERC165,478 ERC20,479 ERC20UniqueExtensions,480 Collection481{}1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56// Anonymous struct7struct Tuple0 {8 address field_0;9 uint256 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 ERC20Events {32 event Transfer(address indexed from, address indexed to, uint256 value);33 event Approval(34 address indexed owner,35 address indexed spender,36 uint256 value37 );38}3940// Selector: 40c10f1941contract ERC20Mintable is Dummy, ERC165 {42 // Selector: mint(address,uint256) 40c10f1943 function mint(address to, uint256 amount) public returns (bool) {44 require(false, stub_error);45 to;46 amount;47 dummy = 0;48 return false;49 }50}5152// Selector: 63034ac553contract ERC20UniqueExtensions is Dummy, ERC165 {54 // Selector: burnFrom(address,uint256) 79cc679055 function burnFrom(address from, uint256 amount) public returns (bool) {56 require(false, stub_error);57 from;58 amount;59 dummy = 0;60 return false;61 }6263 // Selector: mintBulk((address,uint256)[]) 1acf2d5564 function mintBulk(Tuple0[] memory amounts) public returns (bool) {65 require(false, stub_error);66 amounts;67 dummy = 0;68 return false;69 }70}7172// Selector: 6cf113cd73contract Collection is Dummy, ERC165 {74 /// Set collection property.75 ///76 /// @param key Property key.77 /// @param value Propery value.78 /// @dev EVM selector for this function is: 0x2f073f66,79 /// or in textual repr: setCollectionProperty(string,bytes)80 function setCollectionProperty(string memory key, bytes memory value)81 public82 {83 require(false, stub_error);84 key;85 value;86 dummy = 0;87 }8889 /// Delete collection property.90 ///91 /// @param key Property key.92 /// @dev EVM selector for this function is: 0x7b7debce,93 /// or in textual repr: deleteCollectionProperty(string)94 function deleteCollectionProperty(string memory key) public {95 require(false, stub_error);96 key;97 dummy = 0;98 }99100 /// Get collection property.101 ///102 /// @dev Throws error if key not found.103 ///104 /// @param key Property key.105 /// @return bytes The property corresponding to the key.106 /// @dev EVM selector for this function is: 0xcf24fd6d,107 /// or in textual repr: collectionProperty(string)108 function collectionProperty(string memory key)109 public110 view111 returns (bytes memory)112 {113 require(false, stub_error);114 key;115 dummy;116 return hex"";117 }118119 /// Set the sponsor of the collection.120 ///121 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.122 ///123 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.124 /// @dev EVM selector for this function is: 0x7623402e,125 /// or in textual repr: setCollectionSponsor(address)126 function setCollectionSponsor(address sponsor) public {127 require(false, stub_error);128 sponsor;129 dummy = 0;130 }131132 /// Set the substrate sponsor of the collection.133 ///134 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.135 ///136 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.137 /// @dev EVM selector for this function is: 0xc74d6751,138 /// or in textual repr: setCollectionSponsorSubstrate(uint256)139 function setCollectionSponsorSubstrate(uint256 sponsor) public {140 require(false, stub_error);141 sponsor;142 dummy = 0;143 }144145 /// @dev EVM selector for this function is: 0x058ac185,146 /// or in textual repr: hasCollectionPendingSponsor()147 function hasCollectionPendingSponsor() public view returns (bool) {148 require(false, stub_error);149 dummy;150 return false;151 }152153 /// Collection sponsorship confirmation.154 ///155 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.156 /// @dev EVM selector for this function is: 0x3c50e97a,157 /// or in textual repr: confirmCollectionSponsorship()158 function confirmCollectionSponsorship() public {159 require(false, stub_error);160 dummy = 0;161 }162163 /// Remove collection sponsor.164 /// @dev EVM selector for this function is: 0x6e0326a3,165 /// or in textual repr: removeCollectionSponsor()166 function removeCollectionSponsor() public {167 require(false, stub_error);168 dummy = 0;169 }170171 /// Get current sponsor.172 ///173 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.174 /// @dev EVM selector for this function is: 0xb66bbc14,175 /// or in textual repr: getCollectionSponsor()176 function getCollectionSponsor() public view returns (Tuple6 memory) {177 require(false, stub_error);178 dummy;179 return Tuple6(0x0000000000000000000000000000000000000000, 0);180 }181182 /// Set limits for the collection.183 /// @dev Throws error if limit not found.184 /// @param limit Name of the limit. Valid names:185 /// "accountTokenOwnershipLimit",186 /// "sponsoredDataSize",187 /// "sponsoredDataRateLimit",188 /// "tokenLimit",189 /// "sponsorTransferTimeout",190 /// "sponsorApproveTimeout"191 /// @param value Value of the limit.192 /// @dev EVM selector for this function is: 0x6a3841db,193 /// or in textual repr: setCollectionLimit(string,uint32)194 function setCollectionLimit(string memory limit, uint32 value) public {195 require(false, stub_error);196 limit;197 value;198 dummy = 0;199 }200201 /// Set limits for the collection.202 /// @dev Throws error if limit not found.203 /// @param limit Name of the limit. Valid names:204 /// "ownerCanTransfer",205 /// "ownerCanDestroy",206 /// "transfersEnabled"207 /// @param value Value of the limit.208 /// @dev EVM selector for this function is: 0x993b7fba,209 /// or in textual repr: setCollectionLimit(string,bool)210 function setCollectionLimit(string memory limit, bool value) public {211 require(false, stub_error);212 limit;213 value;214 dummy = 0;215 }216217 /// Get contract address.218 /// @dev EVM selector for this function is: 0xf6b4dfb4,219 /// or in textual repr: contractAddress()220 function contractAddress() public view returns (address) {221 require(false, stub_error);222 dummy;223 return 0x0000000000000000000000000000000000000000;224 }225226 /// Add collection admin by substrate address.227 /// @param newAdmin Substrate administrator address.228 /// @dev EVM selector for this function is: 0x5730062b,229 /// or in textual repr: addCollectionAdminSubstrate(uint256)230 function addCollectionAdminSubstrate(uint256 newAdmin) public {231 require(false, stub_error);232 newAdmin;233 dummy = 0;234 }235236 /// Remove collection admin by substrate address.237 /// @param admin Substrate administrator address.238 /// @dev EVM selector for this function is: 0x4048fcf9,239 /// or in textual repr: removeCollectionAdminSubstrate(uint256)240 function removeCollectionAdminSubstrate(uint256 admin) public {241 require(false, stub_error);242 admin;243 dummy = 0;244 }245246 /// Add collection admin.247 /// @param newAdmin Address of the added administrator.248 /// @dev EVM selector for this function is: 0x92e462c7,249 /// or in textual repr: addCollectionAdmin(address)250 function addCollectionAdmin(address newAdmin) public {251 require(false, stub_error);252 newAdmin;253 dummy = 0;254 }255256 /// Remove collection admin.257 ///258 /// @param admin Address of the removed administrator.259 /// @dev EVM selector for this function is: 0xfafd7b42,260 /// or in textual repr: removeCollectionAdmin(address)261 function removeCollectionAdmin(address admin) public {262 require(false, stub_error);263 admin;264 dummy = 0;265 }266267 /// Toggle accessibility of collection nesting.268 ///269 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'270 /// @dev EVM selector for this function is: 0x112d4586,271 /// or in textual repr: setCollectionNesting(bool)272 function setCollectionNesting(bool enable) public {273 require(false, stub_error);274 enable;275 dummy = 0;276 }277278 /// Toggle accessibility of collection nesting.279 ///280 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'281 /// @param collections Addresses of collections that will be available for nesting.282 /// @dev EVM selector for this function is: 0x64872396,283 /// or in textual repr: setCollectionNesting(bool,address[])284 function setCollectionNesting(bool enable, address[] memory collections)285 public286 {287 require(false, stub_error);288 enable;289 collections;290 dummy = 0;291 }292293 /// Set the collection access method.294 /// @param mode Access mode295 /// 0 for Normal296 /// 1 for AllowList297 /// @dev EVM selector for this function is: 0x41835d4c,298 /// or in textual repr: setCollectionAccess(uint8)299 function setCollectionAccess(uint8 mode) public {300 require(false, stub_error);301 mode;302 dummy = 0;303 }304305 /// Add the user to the allowed list.306 ///307 /// @param user Address of a trusted user.308 /// @dev EVM selector for this function is: 0x67844fe6,309 /// or in textual repr: addToCollectionAllowList(address)310 function addToCollectionAllowList(address user) public {311 require(false, stub_error);312 user;313 dummy = 0;314 }315316 /// Remove the user from the allowed list.317 ///318 /// @param user Address of a removed user.319 /// @dev EVM selector for this function is: 0x85c51acb,320 /// or in textual repr: removeFromCollectionAllowList(address)321 function removeFromCollectionAllowList(address user) public {322 require(false, stub_error);323 user;324 dummy = 0;325 }326327 /// Switch permission for minting.328 ///329 /// @param mode Enable if "true".330 /// @dev EVM selector for this function is: 0x00018e84,331 /// or in textual repr: setCollectionMintMode(bool)332 function setCollectionMintMode(bool mode) public {333 require(false, stub_error);334 mode;335 dummy = 0;336 }337338 /// Check that account is the owner or admin of the collection339 ///340 /// @param user account to verify341 /// @return "true" if account is the owner or admin342 /// @dev EVM selector for this function is: 0x9811b0c7,343 /// or in textual repr: isOwnerOrAdmin(address)344 function isOwnerOrAdmin(address user) public view returns (bool) {345 require(false, stub_error);346 user;347 dummy;348 return false;349 }350351 /// Check that substrate account is the owner or admin of the collection352 ///353 /// @param user account to verify354 /// @return "true" if account is the owner or admin355 /// @dev EVM selector for this function is: 0x68910e00,356 /// or in textual repr: isOwnerOrAdminSubstrate(uint256)357 function isOwnerOrAdminSubstrate(uint256 user) public view returns (bool) {358 require(false, stub_error);359 user;360 dummy;361 return false;362 }363364 /// Returns collection type365 ///366 /// @return `Fungible` or `NFT` or `ReFungible`367 /// @dev EVM selector for this function is: 0xd34b55b8,368 /// or in textual repr: uniqueCollectionType()369 function uniqueCollectionType() public returns (string memory) {370 require(false, stub_error);371 dummy = 0;372 return "";373 }374375 /// Changes collection owner to another account376 ///377 /// @dev Owner can be changed only by current owner378 /// @param newOwner new owner account379 /// @dev EVM selector for this function is: 0x13af4035,380 /// or in textual repr: setOwner(address)381 function setOwner(address newOwner) public {382 require(false, stub_error);383 newOwner;384 dummy = 0;385 }386387 /// Changes collection owner to another substrate account388 ///389 /// @dev Owner can be changed only by current owner390 /// @param newOwner new owner substrate account391 /// @dev EVM selector for this function is: 0xb212138f,392 /// or in textual repr: setOwnerSubstrate(uint256)393 function setOwnerSubstrate(uint256 newOwner) public {394 require(false, stub_error);395 newOwner;396 dummy = 0;397 }398}399400/// @dev anonymous struct401struct Tuple6 {402 address field_0;403 uint256 field_1;404}405406/// @dev the ERC-165 identifier for this interface is 0x79cc6790407contract ERC20UniqueExtensions is Dummy, ERC165 {408 /// @dev EVM selector for this function is: 0x79cc6790,409 /// or in textual repr: burnFrom(address,uint256)410 function burnFrom(address from, uint256 amount) public returns (bool) {411 require(false, stub_error);412 from;413 amount;414 dummy = 0;415 return false;416 }417}418419/// @dev inlined interface420contract ERC20Events {421 event Transfer(address indexed from, address indexed to, uint256 value);422 event Approval(423 address indexed owner,424 address indexed spender,425 uint256 value426 );427}428429/// @dev the ERC-165 identifier for this interface is 0x942e8b22430contract ERC20 is Dummy, ERC165, ERC20Events {431 /// @dev EVM selector for this function is: 0x06fdde03,432 /// or in textual repr: name()433 function name() public view returns (string memory) {434 require(false, stub_error);435 dummy;436 return "";437 }438439 /// @dev EVM selector for this function is: 0x95d89b41,440 /// or in textual repr: symbol()441 function symbol() public view returns (string memory) {442 require(false, stub_error);443 dummy;444 return "";445 }446447 /// @dev EVM selector for this function is: 0x18160ddd,448 /// or in textual repr: totalSupply()449 function totalSupply() public view returns (uint256) {450 require(false, stub_error);451 dummy;452 return 0;453 }454455 /// @dev EVM selector for this function is: 0x313ce567,456 /// or in textual repr: decimals()457 function decimals() public view returns (uint8) {458 require(false, stub_error);459 dummy;460 return 0;461 }462463 /// @dev EVM selector for this function is: 0x70a08231,464 /// or in textual repr: balanceOf(address)465 function balanceOf(address owner) public view returns (uint256) {466 require(false, stub_error);467 owner;468 dummy;469 return 0;470 }471472 /// @dev EVM selector for this function is: 0xa9059cbb,473 /// or in textual repr: transfer(address,uint256)474 function transfer(address to, uint256 amount) public returns (bool) {475 require(false, stub_error);476 to;477 amount;478 dummy = 0;479 return false;480 }481482 /// @dev EVM selector for this function is: 0x23b872dd,483 /// or in textual repr: transferFrom(address,address,uint256)484 function transferFrom(485 address from,486 address to,487 uint256 amount488 ) public returns (bool) {489 require(false, stub_error);490 from;491 to;492 amount;493 dummy = 0;494 return false;495 }496497 /// @dev EVM selector for this function is: 0x095ea7b3,498 /// or in textual repr: approve(address,uint256)499 function approve(address spender, uint256 amount) public returns (bool) {500 require(false, stub_error);501 spender;502 amount;503 dummy = 0;504 return false;505 }506507 /// @dev EVM selector for this function is: 0xdd62ed3e,508 /// or in textual repr: allowance(address,address)509 function allowance(address owner, address spender)510 public511 view512 returns (uint256)513 {514 require(false, stub_error);515 owner;516 spender;517 dummy;518 return 0;519 }520}521522contract UniqueFungible is523 Dummy,524 ERC165,525 ERC20,526 ERC20Mintable,527 ERC20UniqueExtensions,528 Collection529{}tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -3,7 +3,13 @@
pragma solidity >=0.8.0 <0.9.0;
-/// @dev common stubs holder
+// Anonymous struct
+struct Tuple0 {
+ address field_0;
+ uint256 field_1;
+}
+
+// Common stubs holder
interface Dummy {
}
@@ -12,8 +18,32 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+// Inline
+interface ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+// Selector: 40c10f19
+interface ERC20Mintable is Dummy, ERC165 {
+ // Selector: mint(address,uint256) 40c10f19
+ function mint(address to, uint256 amount) external returns (bool);
+}
+
+// Selector: 63034ac5
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+ // Selector: burnFrom(address,uint256) 79cc6790
+ function burnFrom(address from, uint256 amount) external returns (bool);
+
+ // Selector: mintBulk((address,uint256)[]) 1acf2d55
+ function mintBulk(Tuple0[] memory amounts) external returns (bool);
+}
+
+// Selector: 6cf113cd
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -207,30 +237,8 @@
/// @dev EVM selector for this function is: 0xd34b55b8,
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
-
- /// Changes collection owner to another account
- ///
- /// @dev Owner can be changed only by current owner
- /// @param newOwner new owner account
- /// @dev EVM selector for this function is: 0x13af4035,
- /// or in textual repr: setOwner(address)
- function setOwner(address newOwner) external;
-
- /// Changes collection owner to another substrate account
- ///
- /// @dev Owner can be changed only by current owner
- /// @param newOwner new owner substrate account
- /// @dev EVM selector for this function is: 0xb212138f,
- /// or in textual repr: setOwnerSubstrate(uint256)
- function setOwnerSubstrate(uint256 newOwner) external;
}
-/// @dev anonymous struct
-struct Tuple6 {
- address field_0;
- uint256 field_1;
-}
-
/// @dev the ERC-165 identifier for this interface is 0x79cc6790
interface ERC20UniqueExtensions is Dummy, ERC165 {
/// @dev EVM selector for this function is: 0x79cc6790,
@@ -298,6 +306,7 @@
Dummy,
ERC165,
ERC20,
+ ERC20Mintable,
ERC20UniqueExtensions,
Collection
{}
tests/src/eth/fungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -14,10 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
+import {approveExpectSuccess, createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
import fungibleAbi from './fungibleAbi.json';
import {expect} from 'chai';
+import {submitTransactionAsync} from '../substrate/substrate-api';
describe('Fungible: Information getting', () => {
itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
@@ -58,6 +59,129 @@
});
describe('Fungible: Plain calls', () => {
+ itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ const collection = await createCollection(api, alice, {
+ name: 'token name',
+ mode: {type: 'Fungible', decimalPoints: 0},
+ });
+
+ const receiver = createEthAccount(web3);
+
+ const collectionIdAddress = collectionIdToAddress(collection.collectionId);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
+ await submitTransactionAsync(alice, changeAdminTx);
+
+ const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
+ const result = await collectionContract.methods.mint(receiver, 100).send();
+ const events = normalizeEvents(result.events);
+
+ expect(events).to.be.deep.equal([
+ {
+ address: collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: receiver,
+ value: '100',
+ },
+ },
+ ]);
+ });
+
+ itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ const collection = await createCollection(api, alice, {
+ name: 'token name',
+ mode: {type: 'Fungible', decimalPoints: 0},
+ });
+
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const receiver1 = createEthAccount(web3);
+ const receiver2 = createEthAccount(web3);
+ const receiver3 = createEthAccount(web3);
+
+ const collectionIdAddress = collectionIdToAddress(collection.collectionId);
+ const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
+ await submitTransactionAsync(alice, changeAdminTx);
+
+ const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
+ const result = await collectionContract.methods.mintBulk([
+ [receiver1, 10],
+ [receiver2, 20],
+ [receiver3, 30],
+ ]).call();
+ console.log(result);
+ const events = normalizeEvents(result.events);
+
+ expect(events).to.be.deep.equal([
+ {
+ address:collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: receiver1,
+ value: '10',
+ },
+ },
+ {
+ address:collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: receiver2,
+ value: '20',
+ },
+ },
+ {
+ address:collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: receiver3,
+ value: '30',
+ },
+ },
+ ]);
+ });
+
+ itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ const collection = await createCollection(api, alice, {
+ name: 'token name',
+ mode: {type: 'Fungible', decimalPoints: 0},
+ });
+
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});
+ await submitTransactionAsync(alice, changeAdminTx);
+ const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const collectionIdAddress = collectionIdToAddress(collection.collectionId);
+ const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});
+ await collectionContract.methods.mint(receiver, 100).send();
+
+ const result = await collectionContract.methods.burnFrom(receiver, 49).send({from: receiver});
+
+ const events = normalizeEvents(result.events);
+
+ expect(events).to.be.deep.equal([
+ {
+ address: collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: receiver,
+ to: '0x0000000000000000000000000000000000000000',
+ value: '49',
+ },
+ },
+ ]);
+
+ const balance = await collectionContract.methods.balanceOf(receiver).call();
+ expect(balance).to.equal('51');
+ });
+
itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
const collection = await createCollectionExpectSuccess({
name: 'token name',
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -151,6 +151,33 @@
"type": "function"
},
{
+ "inputs": [
+ { "internalType": "address", "name": "to", "type": "address" },
+ { "internalType": "uint256", "name": "amount", "type": "uint256" }
+ ],
+ "name": "mint",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple0[]",
+ "name": "amounts",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "mintBulk",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [],
"name": "getCollectionSponsor",
"outputs": [