git.delta.rocks / unique-network / refs/commits / 0902e70cd1b8

difftreelog

CORE-317 Fix ERC165 support interface

Trubnikov Sergey2022-04-11parent: #219f5f0.patch.diff
in: master

7 files changed

modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/solidity_interface.rs
+++ b/crates/evm-coder-macros/src/solidity_interface.rs
@@ -57,7 +57,7 @@
 	fn expand_interface_id(&self) -> proc_macro2::TokenStream {
 		let pascal_call_name = &self.pascal_call_name;
 		quote! {
-			interface_id ^= #pascal_call_name::interface_id();
+			interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());
 		}
 	}
 
@@ -540,18 +540,18 @@
 
 	fn expand_const(&self) -> proc_macro2::TokenStream {
 		let screaming_name = &self.screaming_name;
-		let selector = self.selector;
+		let selector = u32::to_be_bytes(self.selector);
 		let selector_str = &self.selector_str;
 		quote! {
 			#[doc = #selector_str]
-			const #screaming_name: u32 = #selector;
+			const #screaming_name: ::evm_coder::types::bytes4 = [#(#selector,)*];
 		}
 	}
 
 	fn expand_interface_id(&self) -> proc_macro2::TokenStream {
 		let screaming_name = &self.screaming_name;
 		quote! {
-			interface_id ^= Self::#screaming_name;
+			interface_id ^= u32::from_be_bytes(Self::#screaming_name);
 		}
 	}
 
@@ -831,14 +831,14 @@
 				#(
 					#consts
 				)*
-				pub fn interface_id() -> u32 {
+				pub fn interface_id() -> ::evm_coder::types::bytes4 {
 					let mut interface_id = 0;
 					#(#interface_id)*
 					#(#inline_interface_id)*
-					interface_id
+					u32::to_be_bytes(interface_id)
 				}
-				pub fn supports_interface(interface_id: u32) -> bool {
-					interface_id != 0xffffff && (
+				pub fn supports_interface(interface_id: ::evm_coder::types::bytes4) -> bool {
+					interface_id != u32::to_be_bytes(0xffffff) && (
 						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||
 						interface_id == Self::interface_id()
 						#(
@@ -884,7 +884,7 @@
 				}
 			}
 			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
-				fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
+				fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
 					use ::evm_coder::abi::AbiRead;
 					match method_id {
 						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
modifiedcrates/evm-coder-macros/src/to_log.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/to_log.rs
+++ b/crates/evm-coder-macros/src/to_log.rs
@@ -199,7 +199,7 @@
 					use evm_coder::solidity::*;
 					use core::fmt::Write;
 					let interface = SolidityInterface {
-						selector: 0,
+						selector: [0; 4],
 						name: #solidity_name,
 						is: &[],
 						functions: (#(
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -26,7 +26,7 @@
 
 use crate::{
 	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},
-	types::string,
+	types::{string, self},
 };
 use crate::execution::Result;
 
@@ -46,7 +46,7 @@
 			offset: 0,
 		}
 	}
-	pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {
+	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {
 		if buf.len() < 4 {
 			return Err(Error::Error(ExitError::OutOfOffset));
 		}
@@ -54,7 +54,7 @@
 		method_id.copy_from_slice(&buf[0..4]);
 
 		Ok((
-			u32::from_be_bytes(method_id),
+			method_id,
 			Self {
 				buf,
 				subresult_offset: 4,
@@ -63,25 +63,50 @@
 		))
 	}
 
-	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {
-		if self.buf.len() - self.offset < ABI_ALIGNMENT {
+	fn read_pad<const S: usize>(buf: &[u8], offset: usize, pad_start: usize, pad_size: usize, block_start: usize, block_size: usize) -> Result<[u8; S]> {
+		if buf.len() - offset < ABI_ALIGNMENT {
 			return Err(Error::Error(ExitError::OutOfOffset));
 		}
 		let mut block = [0; S];
 		// Verify padding is empty
-		if !self.buf[self.offset..self.offset + ABI_ALIGNMENT - S]
+		if !buf[pad_start..pad_size]
 			.iter()
 			.all(|&v| v == 0)
 		{
 			return Err(Error::Error(ExitError::InvalidRange));
 		}
 		block.copy_from_slice(
-			&self.buf[self.offset + ABI_ALIGNMENT - S..self.offset + ABI_ALIGNMENT],
+			&buf[block_start..block_size],
 		);
+		Ok(block)
+	}
+
+	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {
+		let offset = self.offset;
 		self.offset += ABI_ALIGNMENT;
-		Ok(block)
+		Self::read_pad(
+			self.buf,
+			offset,
+			offset, 
+			offset + ABI_ALIGNMENT - S,
+			offset + ABI_ALIGNMENT - S,
+			offset + ABI_ALIGNMENT
+		)
 	}
 
+	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {
+		let offset = self.offset;
+		self.offset += ABI_ALIGNMENT;
+		Self::read_pad(
+			self.buf,
+			offset,
+			offset + S, 
+			offset + ABI_ALIGNMENT,
+			offset,
+			offset + S
+		)
+	}
+	
 	pub fn address(&mut self) -> Result<H160> {
 		Ok(H160(self.read_padleft()?))
 	}
@@ -96,7 +121,7 @@
 	}
 
 	pub fn bytes4(&mut self) -> Result<[u8; 4]> {
-		self.read_padleft()
+		self.read_padright()
 	}
 
 	pub fn bytes(&mut self) -> Result<Vec<u8>> {
@@ -268,6 +293,7 @@
 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);
@@ -466,7 +492,7 @@
 			"
 		))
 		.unwrap();
-		assert_eq!(call, 0x50bb4e7f);
+		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));
 		assert_eq!(
 			format!("{:?}", decoder.address().unwrap()),
 			"0xad2c0954693c2b5404b7e50967d3481bea432374"
@@ -505,7 +531,7 @@
 			"
 		))
 		.unwrap();
-		assert_eq!(call, 0x36543006);
+		assert_eq!(call, u32::to_be_bytes(0x36543006));
 		let _ = decoder.address().unwrap();
 		let data =
 			<AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -44,7 +44,7 @@
 	pub type uint128 = u128;
 	pub type uint256 = U256;
 
-	pub type bytes4 = u32;
+	pub type bytes4 = [u8; 4];
 
 	pub type topic = H256;
 
@@ -71,7 +71,7 @@
 }
 
 pub trait Call: Sized {
-	fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;
+	fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>>;
 }
 
 pub type Weight = u64;
@@ -93,11 +93,11 @@
 }
 
 impl ERC165Call {
-	pub const INTERFACE_ID: types::bytes4 = 0x01ffc9a7;
+	pub const INTERFACE_ID: types::bytes4 = u32::to_be_bytes(0x01ffc9a7);
 }
 
 impl Call for ERC165Call {
-	fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>> {
+	fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>> {
 		if selector != Self::INTERFACE_ID {
 			return Ok(None);
 		}
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -103,6 +103,7 @@
 	uint64 => "uint64" true = "0",
 	uint128 => "uint128" true = "0",
 	uint256 => "uint256" true = "0",
+	bytes4 => "bytes4" true = "bytes4(0)",
 	address => "address" true = "0x0000000000000000000000000000000000000000",
 	string => "string" false = "\"\"",
 	bytes => "bytes" false = "hex\"\"",
@@ -473,7 +474,7 @@
 }
 
 pub struct SolidityInterface<F: SolidityFunctions> {
-	pub selector: u32,
+	pub selector: bytes4,
 	pub name: &'static str,
 	pub is: &'static [&'static str],
 	pub functions: F,
@@ -486,8 +487,9 @@
 		out: &mut impl fmt::Write,
 		tc: &TypeCollector,
 	) -> fmt::Result {
-		if self.selector != 0 {
-			writeln!(out, "// Selector: {:0>8x}", self.selector)?;
+		const ZERO_BYTES: [u8; 4] = [0; 4];
+		if self.selector != ZERO_BYTES {
+			writeln!(out, "// Selector: {:0>8x}", u32::from_be_bytes(self.selector))?;
 		}
 		if is_impl {
 			write!(out, "contract ")?;
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -14,11 +14,13 @@
 // 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 {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee} from './util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee, usingWeb3} from './util/helpers';
 import {expect} from 'chai';
 import {createCollectionExpectSuccess, createItemExpectSuccess, UNIQUE} from '../util/helpers';
 import nonFungibleAbi from './nonFungibleAbi.json';
 import privateKey from '../substrate/privateKey';
+import {Contract} from 'web3-eth-contract';
+import Web3 from 'web3';
 
 describe('Contract calls', () => {
   itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api}) => {
@@ -59,3 +61,53 @@
     expect(Math.abs(fee - expectedFee)).to.be.lessThan(tolerance);
   });
 });
+
+describe('ERC165 tests', async () => {
+  // https://eips.ethereum.org/EIPS/eip-165
+
+  let collection: number;
+  let minter: string;
+
+  function contract(web3: Web3): Contract {
+    return new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collection), {from: minter, ...GAS_ARGS});
+  }
+
+  before(async () => {
+    await usingWeb3 (async (web3) => {
+      collection = await createCollectionExpectSuccess();
+      minter = createEthAccount(web3);
+    });
+  });
+  
+  itWeb3('interfaceID == 0xffffffff always false', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0xffffffff').call()).to.be.false;
+  });
+
+  itWeb3('ERC721 support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x58800161').call()).to.be.true;
+  });
+
+  itWeb3('ERC721Metadata support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x5b5e139f').call()).to.be.true;
+  });
+
+  itWeb3('ERC721Mintable support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x68ccfe89').call()).to.be.true;
+  });
+
+  itWeb3('ERC721Enumerable support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x780e9d63').call()).to.be.true;
+  });
+
+  itWeb3('ERC721UniqueExtensions support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0xe562194d').call()).to.be.true;
+  });
+
+  itWeb3('ERC721Burnable support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x42966c68').call()).to.be.true;
+  });
+
+  itWeb3('ERC165 support', async ({web3}) => {
+    expect(await contract(web3).methods.supportsInterface('0x01ffc9a7').call()).to.be.true;
+  });
+});
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
before · tests/src/eth/nonFungibleAbi.json
1[2    {3        "anonymous": false,4        "inputs": [5            {6                "indexed": true,7                "internalType": "address",8                "name": "owner",9                "type": "address"10            },11            {12                "indexed": true,13                "internalType": "address",14                "name": "approved",15                "type": "address"16            },17            {18                "indexed": true,19                "internalType": "uint256",20                "name": "tokenId",21                "type": "uint256"22            }23        ],24        "name": "Approval",25        "type": "event"26    },27    {28        "anonymous": false,29        "inputs": [30            {31                "indexed": true,32                "internalType": "address",33                "name": "owner",34                "type": "address"35            },36            {37                "indexed": true,38                "internalType": "address",39                "name": "operator",40                "type": "address"41            },42            {43                "indexed": false,44                "internalType": "bool",45                "name": "approved",46                "type": "bool"47            }48        ],49        "name": "ApprovalForAll",50        "type": "event"51    },52    {53        "anonymous": false,54        "inputs": [],55        "name": "MintingFinished",56        "type": "event"57    },58    {59        "anonymous": false,60        "inputs": [61            {62                "indexed": true,63                "internalType": "address",64                "name": "from",65                "type": "address"66            },67            {68                "indexed": true,69                "internalType": "address",70                "name": "to",71                "type": "address"72            },73            {74                "indexed": true,75                "internalType": "uint256",76                "name": "tokenId",77                "type": "uint256"78            }79        ],80        "name": "Transfer",81        "type": "event"82    },83    {84        "inputs": [85            {86                "internalType": "address",87                "name": "approved",88                "type": "address"89            },90            {91                "internalType": "uint256",92                "name": "tokenId",93                "type": "uint256"94            }95        ],96        "name": "approve",97        "outputs": [],98        "stateMutability": "nonpayable",99        "type": "function"100    },101    {102        "inputs": [103            {104                "internalType": "address",105                "name": "owner",106                "type": "address"107            }108        ],109        "name": "balanceOf",110        "outputs": [111            {112                "internalType": "uint256",113                "name": "",114                "type": "uint256"115            }116        ],117        "stateMutability": "view",118        "type": "function"119    },120    {121        "inputs": [122            {123                "internalType": "uint256",124                "name": "tokenId",125                "type": "uint256"126            }127        ],128        "name": "burn",129        "outputs": [],130        "stateMutability": "nonpayable",131        "type": "function"132    },133    {134        "inputs": [],135        "name": "finishMinting",136        "outputs": [137            {138                "internalType": "bool",139                "name": "",140                "type": "bool"141            }142        ],143        "stateMutability": "nonpayable",144        "type": "function"145    },146    {147        "inputs": [148            {149                "internalType": "uint256",150                "name": "tokenId",151                "type": "uint256"152            }153        ],154        "name": "getApproved",155        "outputs": [156            {157                "internalType": "address",158                "name": "",159                "type": "address"160            }161        ],162        "stateMutability": "view",163        "type": "function"164    },165    {166        "inputs": [167            {168                "internalType": "uint256",169                "name": "tokenId",170                "type": "uint256"171            }172        ],173        "name": "getVariableMetadata",174        "outputs": [175            {176                "internalType": "bytes",177                "name": "",178                "type": "bytes"179            }180        ],181        "stateMutability": "view",182        "type": "function"183    },184    {185        "inputs": [186            {187                "internalType": "address",188                "name": "owner",189                "type": "address"190            },191            {192                "internalType": "address",193                "name": "operator",194                "type": "address"195            }196        ],197        "name": "isApprovedForAll",198        "outputs": [199            {200                "internalType": "address",201                "name": "",202                "type": "address"203            }204        ],205        "stateMutability": "view",206        "type": "function"207    },208    {209        "inputs": [210            {211                "internalType": "address",212                "name": "to",213                "type": "address"214            },215            {216                "internalType": "uint256",217                "name": "tokenId",218                "type": "uint256"219            }220        ],221        "name": "mint",222        "outputs": [223            {224                "internalType": "bool",225                "name": "",226                "type": "bool"227            }228        ],229        "stateMutability": "nonpayable",230        "type": "function"231    },232    {233        "inputs": [234            {235                "internalType": "address",236                "name": "to",237                "type": "address"238            },239            {240                "internalType": "uint256[]",241                "name": "tokenIds",242                "type": "uint256[]"243            }244        ],245        "name": "mintBulk",246        "outputs": [247            {248                "internalType": "bool",249                "name": "",250                "type": "bool"251            }252        ],253        "stateMutability": "nonpayable",254        "type": "function"255    },256    {257        "inputs": [258            {259                "internalType": "address",260                "name": "to",261                "type": "address"262            },263            {264                "components": [265                    {266                        "internalType": "uint256",267                        "name": "field_0",268                        "type": "uint256"269                    },270                    {271                        "internalType": "string",272                        "name": "field_1",273                        "type": "string"274                    }275                ],276                "internalType": "struct Tuple0[]",277                "name": "tokens",278                "type": "tuple[]"279            }280        ],281        "name": "mintBulkWithTokenURI",282        "outputs": [283            {284                "internalType": "bool",285                "name": "",286                "type": "bool"287            }288        ],289        "stateMutability": "nonpayable",290        "type": "function"291    },292    {293        "inputs": [294            {295                "internalType": "address",296                "name": "to",297                "type": "address"298            },299            {300                "internalType": "uint256",301                "name": "tokenId",302                "type": "uint256"303            },304            {305                "internalType": "string",306                "name": "tokenUri",307                "type": "string"308            }309        ],310        "name": "mintWithTokenURI",311        "outputs": [312            {313                "internalType": "bool",314                "name": "",315                "type": "bool"316            }317        ],318        "stateMutability": "nonpayable",319        "type": "function"320    },321    {322        "inputs": [],323        "name": "mintingFinished",324        "outputs": [325            {326                "internalType": "bool",327                "name": "",328                "type": "bool"329            }330        ],331        "stateMutability": "view",332        "type": "function"333    },334    {335        "inputs": [],336        "name": "name",337        "outputs": [338            {339                "internalType": "string",340                "name": "",341                "type": "string"342            }343        ],344        "stateMutability": "view",345        "type": "function"346    },347    {348        "inputs": [],349        "name": "nextTokenId",350        "outputs": [351            {352                "internalType": "uint256",353                "name": "",354                "type": "uint256"355            }356        ],357        "stateMutability": "view",358        "type": "function"359    },360    {361        "inputs": [362            {363                "internalType": "uint256",364                "name": "tokenId",365                "type": "uint256"366            }367        ],368        "name": "ownerOf",369        "outputs": [370            {371                "internalType": "address",372                "name": "",373                "type": "address"374            }375        ],376        "stateMutability": "view",377        "type": "function"378    },379    {380        "inputs": [381            {382                "internalType": "address",383                "name": "from",384                "type": "address"385            },386            {387                "internalType": "address",388                "name": "to",389                "type": "address"390            },391            {392                "internalType": "uint256",393                "name": "tokenId",394                "type": "uint256"395            }396        ],397        "name": "safeTransferFrom",398        "outputs": [],399        "stateMutability": "nonpayable",400        "type": "function"401    },402    {403        "inputs": [404            {405                "internalType": "address",406                "name": "from",407                "type": "address"408            },409            {410                "internalType": "address",411                "name": "to",412                "type": "address"413            },414            {415                "internalType": "uint256",416                "name": "tokenId",417                "type": "uint256"418            },419            {420                "internalType": "bytes",421                "name": "data",422                "type": "bytes"423            }424        ],425        "name": "safeTransferFromWithData",426        "outputs": [],427        "stateMutability": "nonpayable",428        "type": "function"429    },430    {431        "inputs": [432            {433                "internalType": "address",434                "name": "operator",435                "type": "address"436            },437            {438                "internalType": "bool",439                "name": "approved",440                "type": "bool"441            }442        ],443        "name": "setApprovalForAll",444        "outputs": [],445        "stateMutability": "nonpayable",446        "type": "function"447    },448    {449        "inputs": [450            {451                "internalType": "uint256",452                "name": "tokenId",453                "type": "uint256"454            },455            {456                "internalType": "bytes",457                "name": "data",458                "type": "bytes"459            }460        ],461        "name": "setVariableMetadata",462        "outputs": [],463        "stateMutability": "nonpayable",464        "type": "function"465    },466    {467        "inputs": [468            {469                "internalType": "uint32",470                "name": "interfaceId",471                "type": "uint32"472            }473        ],474        "name": "supportsInterface",475        "outputs": [476            {477                "internalType": "bool",478                "name": "",479                "type": "bool"480            }481        ],482        "stateMutability": "view",483        "type": "function"484    },485    {486        "inputs": [],487        "name": "symbol",488        "outputs": [489            {490                "internalType": "string",491                "name": "",492                "type": "string"493            }494        ],495        "stateMutability": "view",496        "type": "function"497    },498    {499        "inputs": [500            {501                "internalType": "uint256",502                "name": "index",503                "type": "uint256"504            }505        ],506        "name": "tokenByIndex",507        "outputs": [508            {509                "internalType": "uint256",510                "name": "",511                "type": "uint256"512            }513        ],514        "stateMutability": "view",515        "type": "function"516    },517    {518        "inputs": [519            {520                "internalType": "address",521                "name": "owner",522                "type": "address"523            },524            {525                "internalType": "uint256",526                "name": "index",527                "type": "uint256"528            }529        ],530        "name": "tokenOfOwnerByIndex",531        "outputs": [532            {533                "internalType": "uint256",534                "name": "",535                "type": "uint256"536            }537        ],538        "stateMutability": "view",539        "type": "function"540    },541    {542        "inputs": [543            {544                "internalType": "uint256",545                "name": "tokenId",546                "type": "uint256"547            }548        ],549        "name": "tokenURI",550        "outputs": [551            {552                "internalType": "string",553                "name": "",554                "type": "string"555            }556        ],557        "stateMutability": "view",558        "type": "function"559    },560    {561        "inputs": [],562        "name": "totalSupply",563        "outputs": [564            {565                "internalType": "uint256",566                "name": "",567                "type": "uint256"568            }569        ],570        "stateMutability": "view",571        "type": "function"572    },573    {574        "inputs": [575            {576                "internalType": "address",577                "name": "to",578                "type": "address"579            },580            {581                "internalType": "uint256",582                "name": "tokenId",583                "type": "uint256"584            }585        ],586        "name": "transfer",587        "outputs": [],588        "stateMutability": "nonpayable",589        "type": "function"590    },591    {592        "inputs": [593            {594                "internalType": "address",595                "name": "from",596                "type": "address"597            },598            {599                "internalType": "address",600                "name": "to",601                "type": "address"602            },603            {604                "internalType": "uint256",605                "name": "tokenId",606                "type": "uint256"607            }608        ],609        "name": "transferFrom",610        "outputs": [],611        "stateMutability": "nonpayable",612        "type": "function"613    }614]
after · tests/src/eth/nonFungibleAbi.json
1[2    {3        "anonymous": false,4        "inputs": [5            {6                "indexed": true,7                "internalType": "address",8                "name": "owner",9                "type": "address"10            },11            {12                "indexed": true,13                "internalType": "address",14                "name": "approved",15                "type": "address"16            },17            {18                "indexed": true,19                "internalType": "uint256",20                "name": "tokenId",21                "type": "uint256"22            }23        ],24        "name": "Approval",25        "type": "event"26    },27    {28        "anonymous": false,29        "inputs": [30            {31                "indexed": true,32                "internalType": "address",33                "name": "owner",34                "type": "address"35            },36            {37                "indexed": true,38                "internalType": "address",39                "name": "operator",40                "type": "address"41            },42            {43                "indexed": false,44                "internalType": "bool",45                "name": "approved",46                "type": "bool"47            }48        ],49        "name": "ApprovalForAll",50        "type": "event"51    },52    {53        "anonymous": false,54        "inputs": [],55        "name": "MintingFinished",56        "type": "event"57    },58    {59        "anonymous": false,60        "inputs": [61            {62                "indexed": true,63                "internalType": "address",64                "name": "from",65                "type": "address"66            },67            {68                "indexed": true,69                "internalType": "address",70                "name": "to",71                "type": "address"72            },73            {74                "indexed": true,75                "internalType": "uint256",76                "name": "tokenId",77                "type": "uint256"78            }79        ],80        "name": "Transfer",81        "type": "event"82    },83    {84        "inputs": [85            {86                "internalType": "address",87                "name": "approved",88                "type": "address"89            },90            {91                "internalType": "uint256",92                "name": "tokenId",93                "type": "uint256"94            }95        ],96        "name": "approve",97        "outputs": [],98        "stateMutability": "nonpayable",99        "type": "function"100    },101    {102        "inputs": [103            {104                "internalType": "address",105                "name": "owner",106                "type": "address"107            }108        ],109        "name": "balanceOf",110        "outputs": [111            {112                "internalType": "uint256",113                "name": "",114                "type": "uint256"115            }116        ],117        "stateMutability": "view",118        "type": "function"119    },120    {121        "inputs": [122            {123                "internalType": "uint256",124                "name": "tokenId",125                "type": "uint256"126            }127        ],128        "name": "burn",129        "outputs": [],130        "stateMutability": "nonpayable",131        "type": "function"132    },133    {134        "inputs": [],135        "name": "finishMinting",136        "outputs": [137            {138                "internalType": "bool",139                "name": "",140                "type": "bool"141            }142        ],143        "stateMutability": "nonpayable",144        "type": "function"145    },146    {147        "inputs": [148            {149                "internalType": "uint256",150                "name": "tokenId",151                "type": "uint256"152            }153        ],154        "name": "getApproved",155        "outputs": [156            {157                "internalType": "address",158                "name": "",159                "type": "address"160            }161        ],162        "stateMutability": "view",163        "type": "function"164    },165    {166        "inputs": [167            {168                "internalType": "uint256",169                "name": "tokenId",170                "type": "uint256"171            }172        ],173        "name": "getVariableMetadata",174        "outputs": [175            {176                "internalType": "bytes",177                "name": "",178                "type": "bytes"179            }180        ],181        "stateMutability": "view",182        "type": "function"183    },184    {185        "inputs": [186            {187                "internalType": "address",188                "name": "owner",189                "type": "address"190            },191            {192                "internalType": "address",193                "name": "operator",194                "type": "address"195            }196        ],197        "name": "isApprovedForAll",198        "outputs": [199            {200                "internalType": "address",201                "name": "",202                "type": "address"203            }204        ],205        "stateMutability": "view",206        "type": "function"207    },208    {209        "inputs": [210            {211                "internalType": "address",212                "name": "to",213                "type": "address"214            },215            {216                "internalType": "uint256",217                "name": "tokenId",218                "type": "uint256"219            }220        ],221        "name": "mint",222        "outputs": [223            {224                "internalType": "bool",225                "name": "",226                "type": "bool"227            }228        ],229        "stateMutability": "nonpayable",230        "type": "function"231    },232    {233        "inputs": [234            {235                "internalType": "address",236                "name": "to",237                "type": "address"238            },239            {240                "internalType": "uint256[]",241                "name": "tokenIds",242                "type": "uint256[]"243            }244        ],245        "name": "mintBulk",246        "outputs": [247            {248                "internalType": "bool",249                "name": "",250                "type": "bool"251            }252        ],253        "stateMutability": "nonpayable",254        "type": "function"255    },256    {257        "inputs": [258            {259                "internalType": "address",260                "name": "to",261                "type": "address"262            },263            {264                "components": [265                    {266                        "internalType": "uint256",267                        "name": "field_0",268                        "type": "uint256"269                    },270                    {271                        "internalType": "string",272                        "name": "field_1",273                        "type": "string"274                    }275                ],276                "internalType": "struct Tuple0[]",277                "name": "tokens",278                "type": "tuple[]"279            }280        ],281        "name": "mintBulkWithTokenURI",282        "outputs": [283            {284                "internalType": "bool",285                "name": "",286                "type": "bool"287            }288        ],289        "stateMutability": "nonpayable",290        "type": "function"291    },292    {293        "inputs": [294            {295                "internalType": "address",296                "name": "to",297                "type": "address"298            },299            {300                "internalType": "uint256",301                "name": "tokenId",302                "type": "uint256"303            },304            {305                "internalType": "string",306                "name": "tokenUri",307                "type": "string"308            }309        ],310        "name": "mintWithTokenURI",311        "outputs": [312            {313                "internalType": "bool",314                "name": "",315                "type": "bool"316            }317        ],318        "stateMutability": "nonpayable",319        "type": "function"320    },321    {322        "inputs": [],323        "name": "mintingFinished",324        "outputs": [325            {326                "internalType": "bool",327                "name": "",328                "type": "bool"329            }330        ],331        "stateMutability": "view",332        "type": "function"333    },334    {335        "inputs": [],336        "name": "name",337        "outputs": [338            {339                "internalType": "string",340                "name": "",341                "type": "string"342            }343        ],344        "stateMutability": "view",345        "type": "function"346    },347    {348        "inputs": [],349        "name": "nextTokenId",350        "outputs": [351            {352                "internalType": "uint256",353                "name": "",354                "type": "uint256"355            }356        ],357        "stateMutability": "view",358        "type": "function"359    },360    {361        "inputs": [362            {363                "internalType": "uint256",364                "name": "tokenId",365                "type": "uint256"366            }367        ],368        "name": "ownerOf",369        "outputs": [370            {371                "internalType": "address",372                "name": "",373                "type": "address"374            }375        ],376        "stateMutability": "view",377        "type": "function"378    },379    {380        "inputs": [381            {382                "internalType": "address",383                "name": "from",384                "type": "address"385            },386            {387                "internalType": "address",388                "name": "to",389                "type": "address"390            },391            {392                "internalType": "uint256",393                "name": "tokenId",394                "type": "uint256"395            }396        ],397        "name": "safeTransferFrom",398        "outputs": [],399        "stateMutability": "nonpayable",400        "type": "function"401    },402    {403        "inputs": [404            {405                "internalType": "address",406                "name": "from",407                "type": "address"408            },409            {410                "internalType": "address",411                "name": "to",412                "type": "address"413            },414            {415                "internalType": "uint256",416                "name": "tokenId",417                "type": "uint256"418            },419            {420                "internalType": "bytes",421                "name": "data",422                "type": "bytes"423            }424        ],425        "name": "safeTransferFromWithData",426        "outputs": [],427        "stateMutability": "nonpayable",428        "type": "function"429    },430    {431        "inputs": [432            {433                "internalType": "address",434                "name": "operator",435                "type": "address"436            },437            {438                "internalType": "bool",439                "name": "approved",440                "type": "bool"441            }442        ],443        "name": "setApprovalForAll",444        "outputs": [],445        "stateMutability": "nonpayable",446        "type": "function"447    },448    {449        "inputs": [450            {451                "internalType": "uint256",452                "name": "tokenId",453                "type": "uint256"454            },455            {456                "internalType": "bytes",457                "name": "data",458                "type": "bytes"459            }460        ],461        "name": "setVariableMetadata",462        "outputs": [],463        "stateMutability": "nonpayable",464        "type": "function"465    },466    {467        "inputs": [468            {469                "internalType": "bytes4",470                "name": "interfaceId",471                "type": "bytes4"472            }473        ],474        "name": "supportsInterface",475        "outputs": [476            {477                "internalType": "bool",478                "name": "",479                "type": "bool"480            }481        ],482        "stateMutability": "view",483        "type": "function"484    },485    {486        "inputs": [],487        "name": "symbol",488        "outputs": [489            {490                "internalType": "string",491                "name": "",492                "type": "string"493            }494        ],495        "stateMutability": "view",496        "type": "function"497    },498    {499        "inputs": [500            {501                "internalType": "uint256",502                "name": "index",503                "type": "uint256"504            }505        ],506        "name": "tokenByIndex",507        "outputs": [508            {509                "internalType": "uint256",510                "name": "",511                "type": "uint256"512            }513        ],514        "stateMutability": "view",515        "type": "function"516    },517    {518        "inputs": [519            {520                "internalType": "address",521                "name": "owner",522                "type": "address"523            },524            {525                "internalType": "uint256",526                "name": "index",527                "type": "uint256"528            }529        ],530        "name": "tokenOfOwnerByIndex",531        "outputs": [532            {533                "internalType": "uint256",534                "name": "",535                "type": "uint256"536            }537        ],538        "stateMutability": "view",539        "type": "function"540    },541    {542        "inputs": [543            {544                "internalType": "uint256",545                "name": "tokenId",546                "type": "uint256"547            }548        ],549        "name": "tokenURI",550        "outputs": [551            {552                "internalType": "string",553                "name": "",554                "type": "string"555            }556        ],557        "stateMutability": "view",558        "type": "function"559    },560    {561        "inputs": [],562        "name": "totalSupply",563        "outputs": [564            {565                "internalType": "uint256",566                "name": "",567                "type": "uint256"568            }569        ],570        "stateMutability": "view",571        "type": "function"572    },573    {574        "inputs": [575            {576                "internalType": "address",577                "name": "to",578                "type": "address"579            },580            {581                "internalType": "uint256",582                "name": "tokenId",583                "type": "uint256"584            }585        ],586        "name": "transfer",587        "outputs": [],588        "stateMutability": "nonpayable",589        "type": "function"590    },591    {592        "inputs": [593            {594                "internalType": "address",595                "name": "from",596                "type": "address"597            },598            {599                "internalType": "address",600                "name": "to",601                "type": "address"602            },603            {604                "internalType": "uint256",605                "name": "tokenId",606                "type": "uint256"607            }608        ],609        "name": "transferFrom",610        "outputs": [],611        "stateMutability": "nonpayable",612        "type": "function"613    }614]