difftreelog
fix After rebase
in: master
8 files changed
crates/evm-coder/src/abi.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -28,10 +28,13 @@
types::{string, self},
};
use crate::execution::Result;
-use crate::solidity::SolidityTypeName;
const ABI_ALIGNMENT: usize = 32;
+trait TypeHelper<T> {
+ fn is_dynamic() -> bool;
+}
+
/// View into RLP data, which provides method to read typed items from it
#[derive(Clone)]
pub struct AbiReader<'i> {
@@ -330,11 +333,18 @@
pub trait AbiRead<T> {
/// Read item from current position, advanding decoder
fn abi_read(&mut self) -> Result<T>;
+
+ /// Size for type aligned to [`ABI_ALIGNMENT`].
fn size() -> usize;
}
macro_rules! impl_abi_readable {
- ($ty:ty, $method:ident) => {
+ ($ty:ty, $method:ident, $dynamic:literal) => {
+ impl TypeHelper<$ty> for $ty {
+ fn is_dynamic() -> bool {
+ $dynamic
+ }
+ }
impl AbiRead<$ty> for AbiReader<'_> {
fn abi_read(&mut self) -> Result<$ty> {
self.$method()
@@ -347,16 +357,16 @@
};
}
-impl_abi_readable!(u8, uint8);
-impl_abi_readable!(u32, uint32);
-impl_abi_readable!(u64, uint64);
-impl_abi_readable!(u128, uint128);
-impl_abi_readable!(U256, uint256);
-impl_abi_readable!([u8; 4], bytes4);
-impl_abi_readable!(H160, address);
-impl_abi_readable!(Vec<u8>, bytes);
-impl_abi_readable!(bool, bool);
-impl_abi_readable!(string, string);
+impl_abi_readable!(u8, uint8, false);
+impl_abi_readable!(u32, uint32, false);
+impl_abi_readable!(u64, uint64, false);
+impl_abi_readable!(u128, uint128, false);
+impl_abi_readable!(U256, uint256, false);
+impl_abi_readable!([u8; 4], bytes4, false);
+impl_abi_readable!(H160, address, false);
+impl_abi_readable!(Vec<u8>, bytes, true);
+impl_abi_readable!(bool, bool, true);
+impl_abi_readable!(string, string, true);
mod sealed {
/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead
@@ -389,16 +399,24 @@
macro_rules! impl_tuples {
($($ident:ident)+) => {
+ impl<$($ident: TypeHelper<$ident>,)+> TypeHelper<($($ident,)+)> for ($($ident,)+) {
+ fn is_dynamic() -> bool {
+ false
+ $(
+ || <$ident>::is_dynamic()
+ )*
+ }
+ }
impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>
where
$(
Self: AbiRead<$ident>,
)+
- ($($ident,)+): SolidityTypeName,
+ ($($ident,)+): TypeHelper<($($ident,)+)>,
{
fn abi_read(&mut self) -> Result<($($ident,)+)> {
- let size = if <($($ident,)+)>::is_simple() { Some(<Self as AbiRead<($($ident,)+)>>::size()) } else { None };
+ let size = if !<($($ident,)+)>::is_dynamic() { Some(<Self as AbiRead<($($ident,)+)>>::size()) } else { None };
let mut subresult = self.subresult(size)?;
Ok((
$(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+
crates/evm-coder/src/solidity.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -192,10 +192,7 @@
write!(writer, "{}", tc.collect_tuple::<Self>())
}
fn is_simple() -> bool {
- true
- $(
- && <$ident>::is_simple()
- )*
+ false
}
#[allow(unused_assignments)]
fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -129,7 +129,7 @@
}
}
-#[solidity_interface(name = "ERC20Mintable")]
+#[solidity_interface(name = ERC20Mintable)]
impl<T: Config> FungibleHandle<T> {
/// Mint tokens for `to` account.
/// @param to account that will receive minted tokens
@@ -148,7 +148,7 @@
}
}
-#[solidity_interface(name = "ERC20UniqueExtensions")]
+#[solidity_interface(name = ERC20UniqueExtensions)]
impl<T: Config> FungibleHandle<T> {
/// Burn tokens from account
/// @dev Function that burns an `amount` of the tokens of a given account,
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
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- address field_0;
- uint256 field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
contract Dummy {
uint8 dummy;
string stub_error = "this contract is implemented in native";
@@ -27,49 +21,8 @@
}
}
-// Inline
-contract ERC20Events {
- event Transfer(address indexed from, address indexed to, uint256 value);
- event Approval(
- address indexed owner,
- address indexed spender,
- uint256 value
- );
-}
-
-// Selector: 40c10f19
-contract ERC20Mintable is Dummy, ERC165 {
- // Selector: mint(address,uint256) 40c10f19
- function mint(address to, uint256 amount) public returns (bool) {
- require(false, stub_error);
- to;
- amount;
- dummy = 0;
- return false;
- }
-}
-
-// Selector: 63034ac5
-contract ERC20UniqueExtensions is Dummy, ERC165 {
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) public returns (bool) {
- require(false, stub_error);
- from;
- amount;
- dummy = 0;
- return false;
- }
-
- // Selector: mintBulk((address,uint256)[]) 1acf2d55
- function mintBulk(Tuple0[] memory amounts) public returns (bool) {
- require(false, stub_error);
- amounts;
- dummy = 0;
- return false;
- }
-}
-
-// Selector: 6cf113cd
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xe54be640
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -397,19 +350,51 @@
}
}
+/// @dev the ERC-165 identifier for this interface is 0x63034ac5
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+ /// Burn tokens from account
+ /// @dev Function that burns an `amount` of the tokens of a given account,
+ /// deducting from the sender's allowance for said account.
+ /// @param from The account whose tokens will be burnt.
+ /// @param amount The amount that will be burnt.
+ /// @dev EVM selector for this function is: 0x79cc6790,
+ /// or in textual repr: burnFrom(address,uint256)
+ function burnFrom(address from, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ from;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ /// Mint tokens for multiple accounts.
+ /// @param amounts array of pairs of account address and amount
+ /// @dev EVM selector for this function is: 0x1acf2d55,
+ /// or in textual repr: mintBulk((address,uint256)[])
+ function mintBulk(Tuple6[] memory amounts) public returns (bool) {
+ require(false, stub_error);
+ amounts;
+ dummy = 0;
+ return false;
+ }
+}
+
/// @dev anonymous struct
struct Tuple6 {
address field_0;
uint256 field_1;
}
-/// @dev the ERC-165 identifier for this interface is 0x79cc6790
-contract ERC20UniqueExtensions is Dummy, ERC165 {
- /// @dev EVM selector for this function is: 0x79cc6790,
- /// or in textual repr: burnFrom(address,uint256)
- function burnFrom(address from, uint256 amount) public returns (bool) {
+/// @dev the ERC-165 identifier for this interface is 0x40c10f19
+contract ERC20Mintable is Dummy, ERC165 {
+ /// Mint tokens for `to` account.
+ /// @param to account that will receive minted tokens
+ /// @param amount amount of tokens to mint
+ /// @dev EVM selector for this function is: 0x40c10f19,
+ /// or in textual repr: mint(address,uint256)
+ function mint(address to, uint256 amount) public returns (bool) {
require(false, stub_error);
- from;
+ to;
amount;
dummy = 0;
return false;
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -3,13 +3,7 @@
pragma solidity >=0.8.0 <0.9.0;
-// Anonymous struct
-struct Tuple0 {
- address field_0;
- uint256 field_1;
-}
-
-// Common stubs holder
+/// @dev common stubs holder
interface Dummy {
}
@@ -18,32 +12,8 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// 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
+/// @title A contract that allows you to work with collections.
+/// @dev the ERC-165 identifier for this interface is 0xe54be640
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -237,13 +207,56 @@
/// @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 the ERC-165 identifier for this interface is 0x79cc6790
+/// @dev the ERC-165 identifier for this interface is 0x63034ac5
interface ERC20UniqueExtensions is Dummy, ERC165 {
+ /// Burn tokens from account
+ /// @dev Function that burns an `amount` of the tokens of a given account,
+ /// deducting from the sender's allowance for said account.
+ /// @param from The account whose tokens will be burnt.
+ /// @param amount The amount that will be burnt.
/// @dev EVM selector for this function is: 0x79cc6790,
/// or in textual repr: burnFrom(address,uint256)
function burnFrom(address from, uint256 amount) external returns (bool);
+
+ /// Mint tokens for multiple accounts.
+ /// @param amounts array of pairs of account address and amount
+ /// @dev EVM selector for this function is: 0x1acf2d55,
+ /// or in textual repr: mintBulk((address,uint256)[])
+ function mintBulk(Tuple6[] memory amounts) external returns (bool);
+}
+
+/// @dev anonymous struct
+struct Tuple6 {
+ address field_0;
+ uint256 field_1;
+}
+
+/// @dev the ERC-165 identifier for this interface is 0x40c10f19
+interface ERC20Mintable is Dummy, ERC165 {
+ /// Mint tokens for `to` account.
+ /// @param to account that will receive minted tokens
+ /// @param amount amount of tokens to mint
+ /// @dev EVM selector for this function is: 0x40c10f19,
+ /// or in textual repr: mint(address,uint256)
+ function mint(address to, uint256 amount) external returns (bool);
}
/// @dev inlined interface
tests/src/eth/base.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {18 collectionIdToAddress,19 createEthAccount,20 createEthAccountWithBalance,21 deployFlipper,22 ethBalanceViaSub,23 GAS_ARGS,24 itWeb3,25 recordEthFee,26 usingWeb3,27} from './util/helpers';28import {expect} from 'chai';29import {createCollectionExpectSuccess, createItemExpectSuccess, UNIQUE} from '../util/helpers';30import nonFungibleAbi from './nonFungibleAbi.json';31import {Contract} from 'web3-eth-contract';32import Web3 from 'web3';3334describe('Contract calls', () => {35 itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {36 const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);37 const flipper = await deployFlipper(web3, deployer);3839 const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer}));40 expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;41 });4243 itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {44 const userA = await createEthAccountWithBalance(api, web3, privateKeyWrapper);45 const userB = createEthAccount(web3);4647 const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));48 const balanceB = await ethBalanceViaSub(api, userB);49 expect(cost - balanceB < BigInt(0.2 * Number(UNIQUE))).to.be.true;50 });5152 itWeb3('NFT transfer is close to 0.15 UNQ', async ({web3, api, privateKeyWrapper}) => {53 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);54 const receiver = createEthAccount(web3);5556 const alice = privateKeyWrapper('//Alice');57 const collection = await createCollectionExpectSuccess({58 mode: {type: 'NFT'},59 });60 const itemId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});6162 const address = collectionIdToAddress(collection);63 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});6465 const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, itemId).send(caller));6667 const fee = Number(cost) / Number(UNIQUE);68 const expectedFee = 0.15;69 const tolerance = 0.001;7071 expect(Math.abs(fee - expectedFee)).to.be.lessThan(tolerance);72 });73});7475describe('ERC165 tests', async () => {76 // https://eips.ethereum.org/EIPS/eip-1657778 let collection: number;79 let minter: string;8081 function contract(web3: Web3): Contract {82 return new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collection), {from: minter, ...GAS_ARGS});83 }8485 before(async () => {86 await usingWeb3 (async (web3) => {87 collection = await createCollectionExpectSuccess();88 minter = createEthAccount(web3);89 });90 });9192 itWeb3('interfaceID == 0xffffffff always false', async ({web3}) => {93 expect(await contract(web3).methods.supportsInterface('0xffffffff').call()).to.be.false;94 });9596 itWeb3('ERC721 support', async ({web3}) => {97 expect(await contract(web3).methods.supportsInterface('0x58800161').call()).to.be.true;98 });99100 itWeb3('ERC721Metadata support', async ({web3}) => {101 expect(await contract(web3).methods.supportsInterface('0x5b5e139f').call()).to.be.true;102 });103104 itWeb3('ERC721Mintable support', async ({web3}) => {105 expect(await contract(web3).methods.supportsInterface('0x68ccfe89').call()).to.be.true;106 });107108 itWeb3('ERC721Enumerable support', async ({web3}) => {109 expect(await contract(web3).methods.supportsInterface('0x780e9d63').call()).to.be.true;110 });111112 itWeb3('ERC721UniqueExtensions support', async ({web3}) => {113 expect(await contract(web3).methods.supportsInterface('0xd74d154f').call()).to.be.true;114 });115116 itWeb3('ERC721Burnable support', async ({web3}) => {117 expect(await contract(web3).methods.supportsInterface('0x42966c68').call()).to.be.true;118 });119120 itWeb3('ERC165 support', async ({web3}) => {121 expect(await contract(web3).methods.supportsInterface('0x01ffc9a7').call()).to.be.true;122 });123});tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -151,33 +151,6 @@
"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": [
@@ -220,6 +193,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 Tuple6[]",
+ "name": "amounts",
+ "type": "tuple[]"
+ }
+ ],
+ "name": "mintBulk",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [],
"name": "name",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],