difftreelog
Merge pull request #719 from UniqueNetwork/feature/transferCross
in: master
26 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6121,7 +6121,7 @@
[[package]]
name = "pallet-fungible"
-version = "0.1.6"
+version = "0.1.7"
dependencies = [
"ethereum",
"evm-coder",
@@ -6376,7 +6376,7 @@
[[package]]
name = "pallet-nonfungible"
-version = "0.1.8"
+version = "0.1.9"
dependencies = [
"ethereum",
"evm-coder",
@@ -6498,7 +6498,7 @@
[[package]]
name = "pallet-refungible"
-version = "0.2.7"
+version = "0.2.8"
dependencies = [
"derivative",
"ethereum",
pallets/fungible/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445<!-- bureaucrate goes here -->67## [0.1.7] - 2022-11-1489### Changed1011- Added `transfer_cross` in eth functions.125## [0.1.6] - 2022-11-0213## [0.1.6] - 2022-11-02146### Changed15### Changed7 - Use named structure `EthCrossAccount` in eth functions.81617- Use named structure `EthCrossAccount` in eth functions.189## [0.1.5] - 2022-08-2919## [0.1.5] - 2022-08-29102011### Added21### Added122213 - Implementation of `mint` and `mint_bulk` methods for ERC20 API.23- Implementation of `mint` and `mint_bulk` methods for ERC20 API.142415## [v0.1.4] - 2022-08-2425## [v0.1.4] - 2022-08-24162617### Change27### Change18 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.192820<!-- bureaucrate goes here -->29- Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.3021## [v0.1.3] 2022-08-1631## [v0.1.3] 2022-08-162232415142### Fixed52### Fixed435344 - Issue with ItemCreated event containing total supply of tokens instead minted amount54- Issue with ItemCreated event containing total supply of tokens instead minted amount455546## [0.1.1] - 2022-07-1456## [0.1.1] - 2022-07-14475748### Added58### Added495950 - Implementation of RPC method `token_owners` returning 10 owners in no particular order.60- Implementation of RPC method `token_owners` returning 10 owners in no particular order.51 This was an internal request to improve the web interface and support fractionalization event.61 This was an internal request to improve the web interface and support fractionalization event.5262pallets/fungible/Cargo.tomldiffbeforeafterboth--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-fungible"
-version = "0.1.6"
+version = "0.1.7"
license = "GPLv3"
edition = "2021"
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -93,6 +93,7 @@
<Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
Ok(true)
}
+
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from(
&mut self,
@@ -238,6 +239,24 @@
Ok(true)
}
+ #[weight(<SelfWeightOf<T>>::transfer())]
+ fn transfer_cross(
+ &mut self,
+ caller: caller,
+ to: EthCrossAccount,
+ amount: uint256,
+ ) -> Result<bool> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = to.into_sub_cross_account::<T>()?;
+ let amount = amount.try_into().map_err(|_| "amount overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+ <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
+ Ok(true)
+ }
+
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from_cross(
&mut self,
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -38,7 +38,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple14[] memory properties) public {
+ function setCollectionProperties(Tuple15[] memory properties) public {
require(false, stub_error);
properties;
dummy = 0;
@@ -87,11 +87,11 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) public view returns (Tuple14[] memory) {
+ function collectionProperties(string[] memory keys) public view returns (Tuple15[] memory) {
require(false, stub_error);
keys;
dummy;
- return new Tuple14[](0);
+ return new Tuple15[](0);
}
/// Set the sponsor of the collection.
@@ -439,12 +439,12 @@
}
/// @dev anonymous struct
-struct Tuple14 {
+struct Tuple15 {
string field_0;
bytes field_1;
}
-/// @dev the ERC-165 identifier for this interface is 0x032e5926
+/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
contract ERC20UniqueExtensions is Dummy, ERC165 {
/// @dev EVM selector for this function is: 0x0ecd0ab0,
/// or in textual repr: approveCross((address,uint256),uint256)
@@ -497,6 +497,16 @@
return false;
}
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ to;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
/// @dev EVM selector for this function is: 0xd5cf430b,
/// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
function transferFromCross(
pallets/nonfungible/CHANGELOG.mddiffbeforeafterboth--- a/pallets/nonfungible/CHANGELOG.md
+++ b/pallets/nonfungible/CHANGELOG.md
@@ -4,6 +4,12 @@
<!-- bureaucrate goes here -->
+## [0.1.9] - 2022-11-14
+
+### Changed
+
+- Added `transfer_cross` in eth functions.
+
## [v0.1.8] - 2022-11-11
### Changed
pallets/nonfungible/Cargo.tomldiffbeforeafterboth--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-nonfungible"
-version = "0.1.8"
+version = "0.1.9"
license = "GPLv3"
edition = "2021"
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -739,6 +739,29 @@
Ok(())
}
+ /// @notice Transfer ownership of an NFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ #[weight(<SelfWeightOf<T>>::transfer())]
+ fn transfer_cross(
+ &mut self,
+ caller: caller,
+ to: EthCrossAccount,
+ token_id: uint256,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = to.into_sub_cross_account::<T>()?;
+ let token = token_id.try_into()?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+ <Pallet<T>>::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
/// @notice Transfer ownership of an NFT from cross account address to cross account address
/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
/// is the zero address. Throws if `tokenId` is not a valid NFT.
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -67,7 +67,7 @@
/// @param properties settable properties
/// @dev EVM selector for this function is: 0x14ed3a6e,
/// or in textual repr: setProperties(uint256,(string,bytes)[])
- function setProperties(uint256 tokenId, Tuple21[] memory properties) public {
+ function setProperties(uint256 tokenId, Tuple22[] memory properties) public {
require(false, stub_error);
tokenId;
properties;
@@ -137,7 +137,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple21[] memory properties) public {
+ function setCollectionProperties(Tuple22[] memory properties) public {
require(false, stub_error);
properties;
dummy = 0;
@@ -186,11 +186,11 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) public view returns (Tuple21[] memory) {
+ function collectionProperties(string[] memory keys) public view returns (Tuple22[] memory) {
require(false, stub_error);
keys;
dummy;
- return new Tuple21[](0);
+ return new Tuple22[](0);
}
/// Set the sponsor of the collection.
@@ -251,10 +251,10 @@
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
/// @dev EVM selector for this function is: 0x6ec0a9f1,
/// or in textual repr: collectionSponsor()
- function collectionSponsor() public view returns (Tuple24 memory) {
+ function collectionSponsor() public view returns (Tuple25 memory) {
require(false, stub_error);
dummy;
- return Tuple24(0x0000000000000000000000000000000000000000, 0);
+ return Tuple25(0x0000000000000000000000000000000000000000, 0);
}
/// Set limits for the collection.
@@ -538,13 +538,13 @@
}
/// @dev anonymous struct
-struct Tuple24 {
+struct Tuple25 {
address field_0;
uint256 field_1;
}
/// @dev anonymous struct
-struct Tuple21 {
+struct Tuple22 {
string field_0;
bytes field_1;
}
@@ -693,7 +693,7 @@
}
/// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x244543ee
+/// @dev the ERC-165 identifier for this interface is 0x0e9fc611
contract ERC721UniqueExtensions is Dummy, ERC165 {
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev EVM selector for this function is: 0x06fdde03,
@@ -742,6 +742,20 @@
dummy = 0;
}
+ /// @notice Transfer ownership of an NFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 tokenId) public {
+ require(false, stub_error);
+ to;
+ tokenId;
+ dummy = 0;
+ }
+
/// @notice Transfer ownership of an NFT from cross account address to cross account address
/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
/// is the zero address. Throws if `tokenId` is not a valid NFT.
@@ -822,7 +836,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) public returns (bool) {
+ // function mintBulkWithTokenURI(address to, Tuple11[] memory tokens) public returns (bool) {
// require(false, stub_error);
// to;
// tokens;
@@ -833,7 +847,7 @@
}
/// @dev anonymous struct
-struct Tuple10 {
+struct Tuple11 {
uint256 field_0;
string field_1;
}
pallets/refungible/CHANGELOG.mddiffbeforeafterboth--- a/pallets/refungible/CHANGELOG.md
+++ b/pallets/refungible/CHANGELOG.md
@@ -4,6 +4,12 @@
<!-- bureaucrate goes here -->
+## [0.2.8] - 2022-11-14
+
+### Changed
+
+- Added `transfer_cross` in eth functions.
+
## [v0.2.7] - 2022-11-11
### Changed
pallets/refungible/Cargo.tomldiffbeforeafterboth--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-refungible"
-version = "0.2.7"
+version = "0.2.8"
license = "GPLv3"
edition = "2021"
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -756,6 +756,34 @@
/// @param to The new owner
/// @param tokenId The RFT to transfer
#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
+ fn transfer_cross(
+ &mut self,
+ caller: caller,
+ to: EthCrossAccount,
+ token_id: uint256,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let to = to.into_sub_cross_account::<T>()?;
+ let token = token_id.try_into()?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+ let balance = balance(self, token, &caller)?;
+ ensure_single_owner(self, token, balance)?;
+
+ <Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ /// @notice Transfer ownership of an RFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param to The new owner
+ /// @param tokenId The RFT to transfer
+ #[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
fn transfer_from_cross(
&mut self,
caller: caller,
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -67,7 +67,7 @@
/// @param properties settable properties
/// @dev EVM selector for this function is: 0x14ed3a6e,
/// or in textual repr: setProperties(uint256,(string,bytes)[])
- function setProperties(uint256 tokenId, Tuple20[] memory properties) public {
+ function setProperties(uint256 tokenId, Tuple21[] memory properties) public {
require(false, stub_error);
tokenId;
properties;
@@ -137,7 +137,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple20[] memory properties) public {
+ function setCollectionProperties(Tuple21[] memory properties) public {
require(false, stub_error);
properties;
dummy = 0;
@@ -186,11 +186,11 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) public view returns (Tuple20[] memory) {
+ function collectionProperties(string[] memory keys) public view returns (Tuple21[] memory) {
require(false, stub_error);
keys;
dummy;
- return new Tuple20[](0);
+ return new Tuple21[](0);
}
/// Set the sponsor of the collection.
@@ -251,10 +251,10 @@
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
/// @dev EVM selector for this function is: 0x6ec0a9f1,
/// or in textual repr: collectionSponsor()
- function collectionSponsor() public view returns (Tuple23 memory) {
+ function collectionSponsor() public view returns (Tuple24 memory) {
require(false, stub_error);
dummy;
- return Tuple23(0x0000000000000000000000000000000000000000, 0);
+ return Tuple24(0x0000000000000000000000000000000000000000, 0);
}
/// Set limits for the collection.
@@ -538,13 +538,13 @@
}
/// @dev anonymous struct
-struct Tuple23 {
+struct Tuple24 {
address field_0;
uint256 field_1;
}
/// @dev anonymous struct
-struct Tuple20 {
+struct Tuple21 {
string field_0;
bytes field_1;
}
@@ -691,7 +691,7 @@
}
/// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x81feb398
+/// @dev the ERC-165 identifier for this interface is 0xab243667
contract ERC721UniqueExtensions is Dummy, ERC165 {
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev EVM selector for this function is: 0x06fdde03,
@@ -732,6 +732,21 @@
/// Throws if RFT pieces have multiple owners.
/// @param to The new owner
/// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 tokenId) public {
+ require(false, stub_error);
+ to;
+ tokenId;
+ dummy = 0;
+ }
+
+ /// @notice Transfer ownership of an RFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param to The new owner
+ /// @param tokenId The RFT to transfer
/// @dev EVM selector for this function is: 0xd5cf430b,
/// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
function transferFromCross(
@@ -809,7 +824,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple9[] memory tokens) public returns (bool) {
+ // function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) public returns (bool) {
// require(false, stub_error);
// to;
// tokens;
@@ -831,7 +846,7 @@
}
/// @dev anonymous struct
-struct Tuple9 {
+struct Tuple10 {
uint256 field_0;
string field_1;
}
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -28,7 +28,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple14[] memory properties) external;
+ function setCollectionProperties(Tuple15[] memory properties) external;
/// Delete collection property.
///
@@ -60,7 +60,7 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) external view returns (Tuple14[] memory);
+ function collectionProperties(string[] memory keys) external view returns (Tuple15[] memory);
/// Set the sponsor of the collection.
///
@@ -287,12 +287,12 @@
}
/// @dev anonymous struct
-struct Tuple14 {
+struct Tuple15 {
string field_0;
bytes field_1;
}
-/// @dev the ERC-165 identifier for this interface is 0x032e5926
+/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
interface ERC20UniqueExtensions is Dummy, ERC165 {
/// @dev EVM selector for this function is: 0x0ecd0ab0,
/// or in textual repr: approveCross((address,uint256),uint256)
@@ -322,6 +322,10 @@
/// or in textual repr: mintBulk((address,uint256)[])
function mintBulk(Tuple8[] memory amounts) external returns (bool);
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 amount) external returns (bool);
+
/// @dev EVM selector for this function is: 0xd5cf430b,
/// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
function transferFromCross(
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -49,7 +49,7 @@
/// @param properties settable properties
/// @dev EVM selector for this function is: 0x14ed3a6e,
/// or in textual repr: setProperties(uint256,(string,bytes)[])
- function setProperties(uint256 tokenId, Tuple21[] memory properties) external;
+ function setProperties(uint256 tokenId, Tuple22[] memory properties) external;
// /// @notice Delete token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -93,7 +93,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple21[] memory properties) external;
+ function setCollectionProperties(Tuple22[] memory properties) external;
/// Delete collection property.
///
@@ -125,7 +125,7 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
+ function collectionProperties(string[] memory keys) external view returns (Tuple22[] memory);
/// Set the sponsor of the collection.
///
@@ -167,7 +167,7 @@
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
/// @dev EVM selector for this function is: 0x6ec0a9f1,
/// or in textual repr: collectionSponsor()
- function collectionSponsor() external view returns (Tuple24 memory);
+ function collectionSponsor() external view returns (Tuple25 memory);
/// Set limits for the collection.
/// @dev Throws error if limit not found.
@@ -352,13 +352,13 @@
}
/// @dev anonymous struct
-struct Tuple24 {
+struct Tuple25 {
address field_0;
uint256 field_1;
}
/// @dev anonymous struct
-struct Tuple21 {
+struct Tuple22 {
string field_0;
bytes field_1;
}
@@ -458,7 +458,7 @@
}
/// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x244543ee
+/// @dev the ERC-165 identifier for this interface is 0x0e9fc611
interface ERC721UniqueExtensions is Dummy, ERC165 {
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev EVM selector for this function is: 0x06fdde03,
@@ -489,6 +489,15 @@
/// or in textual repr: transfer(address,uint256)
function transfer(address to, uint256 tokenId) external;
+ /// @notice Transfer ownership of an NFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid NFT.
+ /// @param to The new owner
+ /// @param tokenId The NFT to transfer
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 tokenId) external;
+
/// @notice Transfer ownership of an NFT from cross account address to cross account address
/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
/// is the zero address. Throws if `tokenId` is not a valid NFT.
@@ -543,12 +552,12 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) external returns (bool);
+ // function mintBulkWithTokenURI(address to, Tuple11[] memory tokens) external returns (bool);
}
/// @dev anonymous struct
-struct Tuple10 {
+struct Tuple11 {
uint256 field_0;
string field_1;
}
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -49,7 +49,7 @@
/// @param properties settable properties
/// @dev EVM selector for this function is: 0x14ed3a6e,
/// or in textual repr: setProperties(uint256,(string,bytes)[])
- function setProperties(uint256 tokenId, Tuple20[] memory properties) external;
+ function setProperties(uint256 tokenId, Tuple21[] memory properties) external;
// /// @notice Delete token property value.
// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -93,7 +93,7 @@
/// @param properties Vector of properties key/value pair.
/// @dev EVM selector for this function is: 0x50b26b2a,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple20[] memory properties) external;
+ function setCollectionProperties(Tuple21[] memory properties) external;
/// Delete collection property.
///
@@ -125,7 +125,7 @@
/// @return Vector of properties key/value pairs.
/// @dev EVM selector for this function is: 0x285fb8e6,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) external view returns (Tuple20[] memory);
+ function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
/// Set the sponsor of the collection.
///
@@ -167,7 +167,7 @@
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
/// @dev EVM selector for this function is: 0x6ec0a9f1,
/// or in textual repr: collectionSponsor()
- function collectionSponsor() external view returns (Tuple23 memory);
+ function collectionSponsor() external view returns (Tuple24 memory);
/// Set limits for the collection.
/// @dev Throws error if limit not found.
@@ -352,13 +352,13 @@
}
/// @dev anonymous struct
-struct Tuple23 {
+struct Tuple24 {
address field_0;
uint256 field_1;
}
/// @dev anonymous struct
-struct Tuple20 {
+struct Tuple21 {
string field_0;
bytes field_1;
}
@@ -456,7 +456,7 @@
}
/// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x81feb398
+/// @dev the ERC-165 identifier for this interface is 0xab243667
interface ERC721UniqueExtensions is Dummy, ERC165 {
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev EVM selector for this function is: 0x06fdde03,
@@ -484,6 +484,16 @@
/// Throws if RFT pieces have multiple owners.
/// @param to The new owner
/// @param tokenId The RFT to transfer
+ /// @dev EVM selector for this function is: 0x2ada85ff,
+ /// or in textual repr: transferCross((address,uint256),uint256)
+ function transferCross(EthCrossAccount memory to, uint256 tokenId) external;
+
+ /// @notice Transfer ownership of an RFT
+ /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+ /// is the zero address. Throws if `tokenId` is not a valid RFT.
+ /// Throws if RFT pieces have multiple owners.
+ /// @param to The new owner
+ /// @param tokenId The RFT to transfer
/// @dev EVM selector for this function is: 0xd5cf430b,
/// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
function transferFromCross(
@@ -535,7 +545,7 @@
// /// @param tokens array of pairs of token ID and token URI for minted tokens
// /// @dev EVM selector for this function is: 0x36543006,
// /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
- // function mintBulkWithTokenURI(address to, Tuple9[] memory tokens) external returns (bool);
+ // function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) external returns (bool);
/// Returns EVM address for refungible token
///
@@ -546,7 +556,7 @@
}
/// @dev anonymous struct
-struct Tuple9 {
+struct Tuple10 {
uint256 field_0;
string field_1;
}
tests/src/eth/base.test.tsdiffbeforeafterboth--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -117,7 +117,7 @@
});
itEth('ERC721UniqueExtensions support', async ({helper}) => {
- await checkInterface(helper, '0x244543ee', true, true);
+ await checkInterface(helper, '0x0e9fc611', true, true);
});
itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {
tests/src/eth/fungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -230,6 +230,59 @@
}
});
+ itEth('Can perform transferCross()', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const to = helper.ethCrossAccount.fromAddress(receiver);
+ const toSubstrate = helper.ethCrossAccount.fromKeyringPair(donor);
+ const collection = await helper.ft.mintCollection(alice);
+ await collection.mint(alice, 200n, {Ethereum: owner});
+
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
+
+ {
+ const result = await contract.methods.transferCross(to, 50).send({from: owner});
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.value).to.be.equal('50');
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(150);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(50);
+ }
+
+ {
+ const result = await contract.methods.transferCross(toSubstrate, 50).send({from: owner});
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(donor.address));
+ expect(event.returnValues.value).to.be.equal('50');
+ }
+
+ {
+ const balance = await collection.getBalance({Ethereum: owner});
+ expect(balance).to.equal(100n);
+ }
+
+ {
+ const balance = await collection.getBalance({Substrate: donor.address});
+ expect(balance).to.equal(50n);
+ }
+
+ });
+
itEth('Can perform transfer()', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const receiver = await helper.eth.createAccountWithBalance(donor);
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -239,7 +239,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple14[]",
+ "internalType": "struct Tuple15[]",
"name": "",
"type": "tuple[]"
}
@@ -496,7 +496,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple14[]",
+ "internalType": "struct Tuple15[]",
"name": "properties",
"type": "tuple[]"
}
@@ -594,6 +594,24 @@
},
{
"inputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "eth", "type": "address" },
+ { "internalType": "uint256", "name": "sub", "type": "uint256" }
+ ],
+ "internalType": "struct EthCrossAccount",
+ "name": "to",
+ "type": "tuple"
+ },
+ { "internalType": "uint256", "name": "amount", "type": "uint256" }
+ ],
+ "name": "transferCross",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
tests/src/eth/nonFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -402,6 +402,60 @@
expect(+balance).to.equal(1);
}
});
+
+ itEth('Can perform transferCross()', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(minter, {});
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const to = helper.ethCrossAccount.fromAddress(receiver);
+ const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);
+
+ const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});
+
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ {
+ const result = await contract.methods.transferCross(to, tokenId).send({from: owner});
+
+ const event = result.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(owner);
+ expect(event.returnValues.to).to.be.equal(receiver);
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(0);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(1);
+ }
+
+ {
+ const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});
+
+
+ const event = substrateResult.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(receiver);
+ expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(0);
+ }
+
+ {
+ const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});
+ expect(balance).to.be.contain(tokenId);
+ }
+ });
});
describe('NFT: Fees', () => {
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -269,7 +269,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple21[]",
+ "internalType": "struct Tuple22[]",
"name": "",
"type": "tuple[]"
}
@@ -293,7 +293,7 @@
{ "internalType": "address", "name": "field_0", "type": "address" },
{ "internalType": "uint256", "name": "field_1", "type": "uint256" }
],
- "internalType": "struct Tuple24",
+ "internalType": "struct Tuple25",
"name": "",
"type": "tuple"
}
@@ -611,7 +611,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple21[]",
+ "internalType": "struct Tuple22[]",
"name": "properties",
"type": "tuple[]"
}
@@ -682,7 +682,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple21[]",
+ "internalType": "struct Tuple22[]",
"name": "properties",
"type": "tuple[]"
}
@@ -778,6 +778,24 @@
},
{
"inputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "eth", "type": "address" },
+ { "internalType": "uint256", "name": "sub", "type": "uint256" }
+ ],
+ "internalType": "struct EthCrossAccount",
+ "name": "to",
+ "type": "tuple"
+ },
+ { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
+ ],
+ "name": "transferCross",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
tests/src/eth/reFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -359,6 +359,59 @@
expect(+balance).to.equal(1);
}
});
+
+ itEth('Can perform transferCross()', async ({helper}) => {
+ const caller = await helper.eth.createAccountWithBalance(donor);
+ const receiver = await helper.eth.createAccountWithBalance(donor);
+ const to = helper.ethCrossAccount.fromAddress(receiver);
+ const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);
+ const collection = await helper.rft.mintCollection(minter, {});
+ const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
+
+ const {tokenId} = await collection.mintToken(minter, 1n, {Ethereum: caller});
+
+ {
+ const result = await contract.methods.transferCross(to, tokenId).send({from: caller});
+
+ const event = result.events.Transfer;
+ expect(event.address).to.equal(collectionAddress);
+ expect(event.returnValues.from).to.equal(caller);
+ expect(event.returnValues.to).to.equal(receiver);
+ expect(event.returnValues.tokenId).to.equal(tokenId.toString());
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(caller).call();
+ expect(+balance).to.equal(0);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(1);
+ }
+
+ {
+ const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});
+
+
+ const event = substrateResult.events.Transfer;
+ expect(event.address).to.be.equal(collectionAddress);
+ expect(event.returnValues.from).to.be.equal(receiver);
+ expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));
+ expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(0);
+ }
+
+ {
+ const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});
+ expect(balance).to.be.contain(tokenId);
+ }
+ });
itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {
const caller = await helper.eth.createAccountWithBalance(donor);
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -251,7 +251,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple20[]",
+ "internalType": "struct Tuple21[]",
"name": "",
"type": "tuple[]"
}
@@ -275,7 +275,7 @@
{ "internalType": "address", "name": "field_0", "type": "address" },
{ "internalType": "uint256", "name": "field_1", "type": "uint256" }
],
- "internalType": "struct Tuple23",
+ "internalType": "struct Tuple24",
"name": "",
"type": "tuple"
}
@@ -593,7 +593,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple20[]",
+ "internalType": "struct Tuple21[]",
"name": "properties",
"type": "tuple[]"
}
@@ -664,7 +664,7 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
- "internalType": "struct Tuple20[]",
+ "internalType": "struct Tuple21[]",
"name": "properties",
"type": "tuple[]"
}
@@ -769,6 +769,24 @@
},
{
"inputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "eth", "type": "address" },
+ { "internalType": "uint256", "name": "sub", "type": "uint256" }
+ ],
+ "internalType": "struct EthCrossAccount",
+ "name": "to",
+ "type": "tuple"
+ },
+ { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
+ ],
+ "name": "transferCross",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }