difftreelog
build update evm stubs
in: master
25 files changed
.maintain/scripts/compile_stub.shdiffbeforeafterboth--- /dev/null
+++ b/.maintain/scripts/compile_stub.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -eu
+
+dir=$PWD
+
+tmp=$(mktemp -d)
+cd $tmp
+cp $dir/$INPUT input.sol
+solcjs --optimize --bin input.sol
+
+mv input_sol_$(basename $OUTPUT .raw).bin out.bin
+xxd -r -p out.bin out.raw
+
+mv out.raw $dir/$OUTPUT
\ No newline at end of file
.maintain/scripts/generate_api.shdiffbeforeafterboth--- /dev/null
+++ b/.maintain/scripts/generate_api.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+tmp=$(mktemp)
+cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp
+raw=$(mktemp --suffix .sol)
+sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
+formatted=$(mktemp)
+prettier --use-tabs $raw > $formatted
+solhint --fix $formatted
+
+mv $formatted $OUTPUT
\ No newline at end of file
Makefilediffbeforeafterboth--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+.PHONY: _eth_codegen
+_eth_codegen:
+
+.PHONY: regenerate_solidity
+regenerate_solidity:
+ PACKAGE=pallet-nft NAME=eth::erc::fungible_iface OUTPUT=./tests/src/eth/api/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
+ PACKAGE=pallet-nft NAME=eth::erc::nft_iface OUTPUT=./tests/src/eth/api/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
+ PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=./tests/src/eth/api/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+
+ PACKAGE=pallet-nft NAME=eth::erc::fungible_impl OUTPUT=./pallets/nft/src/eth/stubs/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
+ PACKAGE=pallet-nft NAME=eth::erc::nft_impl OUTPUT=./pallets/nft/src/eth/stubs/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
+ PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=./pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+
+NFT_EVM_STUBS=./pallets/nft/src/eth/stubs
+CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/
+
+$(NFT_EVM_STUBS)/UniqueFungible.raw: $(NFT_EVM_STUBS)/UniqueFungible.sol
+ INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+$(NFT_EVM_STUBS)/UniqueNFT.raw: $(NFT_EVM_STUBS)/UniqueNFT.sol
+ INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw: $(CONTRACT_HELPERS_STUBS)/ContractHelpers.sol
+ INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+
+evm_stubs: $(NFT_EVM_STUBS)/UniqueFungible.raw $(NFT_EVM_STUBS)/UniqueNFT.raw $(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw
crates/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
@@ -34,8 +34,9 @@
fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
let camel_name = &self.camel_name;
let ty = &self.ty;
+ let indexed = self.indexed;
quote! {
- <NamedArgument<#ty>>::new(#camel_name)
+ <SolidityEventArgument<#ty>>::new(#indexed, #camel_name)
}
}
}
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -61,6 +61,29 @@
fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;
}
+#[macro_export]
+macro_rules! generate_stubgen {
+ ($name:ident, $decl:ident, $is_impl:literal) => {
+ #[test]
+ #[ignore]
+ fn $name() {
+ use sp_std::collections::btree_set::BTreeSet;
+ let mut out = BTreeSet::new();
+ $decl::generate_solidity_interface(&mut out, $is_impl);
+ println!("=== SNIP START ===");
+ println!("// SPDX-License-Identifier: OTHER");
+ println!("// This code is automatically generated");
+ println!();
+ println!("pragma solidity >=0.8.0 <0.9.0;");
+ println!();
+ for b in out {
+ println!("{}", b);
+ }
+ println!("=== SNIP END ===");
+ }
+ };
+}
+
#[cfg(test)]
mod tests {
use super::*;
crates/evm-coder/src/solidity.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -117,6 +117,41 @@
}
}
+pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);
+
+impl<T> SolidityEventArgument<T> {
+ pub fn new(indexed: bool, name: &'static str) -> Self {
+ Self(indexed, name, Default::default())
+ }
+}
+
+impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {
+ fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ if !T::is_void() {
+ T::solidity_name(writer)?;
+ if self.0 {
+ write!(writer, " indexed")?;
+ }
+ write!(writer, " {}", self.1)
+ } else {
+ Ok(())
+ }
+ }
+ fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ writeln!(writer, "\t\t{};", self.1)
+ }
+ fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ T::solidity_default(writer)
+ }
+ fn len(&self) -> usize {
+ if T::is_void() {
+ 0
+ } else {
+ 1
+ }
+ }
+}
+
impl SolidityArguments for () {
fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
Ok(())
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -1,5 +1,5 @@
use core::marker::PhantomData;
-use evm_coder::{abi::AbiWriter, execution::Result, solidity_interface, types::*};
+use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
use pallet_evm_coder_substrate::SubstrateRecorder;
use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};
use sp_core::H160;
@@ -14,76 +14,76 @@
#[solidity_interface(name = "ContractHelpers")]
impl<T: Config> ContractHelpers<T> {
- fn contract_owner(&self, contract: address) -> Result<address> {
+ fn contract_owner(&self, contract_address: address) -> Result<address> {
self.0.consume_sload()?;
- Ok(<Owner<T>>::get(contract))
+ Ok(<Owner<T>>::get(contract_address))
}
- fn sponsoring_enabled(&self, contract: address) -> Result<bool> {
+ fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
self.0.consume_sload()?;
- Ok(<SelfSponsoring<T>>::get(contract))
+ Ok(<SelfSponsoring<T>>::get(contract_address))
}
fn toggle_sponsoring(
&mut self,
caller: caller,
- contract: address,
+ contract_address: address,
enabled: bool,
) -> Result<void> {
self.0.consume_sload()?;
- <Pallet<T>>::ensure_owner(contract, caller)?;
+ <Pallet<T>>::ensure_owner(contract_address, caller)?;
self.0.consume_sstore()?;
- <Pallet<T>>::toggle_sponsoring(contract, enabled);
+ <Pallet<T>>::toggle_sponsoring(contract_address, enabled);
Ok(())
}
fn set_sponsoring_rate_limit(
&mut self,
caller: caller,
- contract: address,
+ contract_address: address,
rate_limit: uint32,
) -> Result<void> {
self.0.consume_sload()?;
- <Pallet<T>>::ensure_owner(contract, caller)?;
+ <Pallet<T>>::ensure_owner(contract_address, caller)?;
self.0.consume_sstore()?;
- <Pallet<T>>::set_sponsoring_rate_limit(contract, rate_limit.into());
+ <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());
Ok(())
}
- fn allowed(&self, contract: address, user: address) -> Result<bool> {
+ fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
self.0.consume_sload()?;
- Ok(<Pallet<T>>::allowed(contract, user, true))
+ Ok(<Pallet<T>>::allowed(contract_address, user, true))
}
- fn allowlist_enabled(&self, contract: address) -> Result<bool> {
+ fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
self.0.consume_sload()?;
- Ok(<AllowlistEnabled<T>>::get(contract))
+ Ok(<AllowlistEnabled<T>>::get(contract_address))
}
fn toggle_allowlist(
&mut self,
caller: caller,
- contract: address,
+ contract_address: address,
enabled: bool,
) -> Result<void> {
self.0.consume_sload()?;
- <Pallet<T>>::ensure_owner(contract, caller)?;
+ <Pallet<T>>::ensure_owner(contract_address, caller)?;
self.0.consume_sstore()?;
- <Pallet<T>>::toggle_allowlist(contract, enabled);
+ <Pallet<T>>::toggle_allowlist(contract_address, enabled);
Ok(())
}
fn toggle_allowed(
&mut self,
caller: caller,
- contract: address,
+ contract_address: address,
user: address,
allowed: bool,
) -> Result<void> {
self.0.consume_sload()?;
- <Pallet<T>>::ensure_owner(contract, caller)?;
+ <Pallet<T>>::ensure_owner(contract_address, caller)?;
self.0.consume_sstore()?;
- <Pallet<T>>::toggle_allowed(contract, user, allowed);
+ <Pallet<T>>::toggle_allowed(contract_address, user, allowed);
Ok(())
}
}
@@ -130,7 +130,7 @@
fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {
(contract == &T::ContractAddress::get())
- .then(|| include_bytes!("./stubs/ContractHelpers.bin").to_vec())
+ .then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())
}
}
@@ -162,3 +162,6 @@
None
}
}
+
+generate_stubgen!(contract_helpers_impl, ContractHelpersCall, true);
+generate_stubgen!(contract_helpers_iface, ContractHelpersCall, false);
pallets/evm-contract-helpers/src/stubs/ContractHelpers.bindiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -1,40 +1,92 @@
-contract ContractHelpers {
- uint8 _dummmy = 0;
- address _dummy_addr = 0x0000000000000000000000000000000000000000;
- string stub_error = "this contract does not exists, contract helpers are implemented on substrate chain side";
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+ uint8 dummy;
+ string stub_error = "this contract is implemented in native";
+}
+
+contract ContractHelpers is Dummy {
+ function contractOwner(address contractAddress)
+ public
+ view
+ returns (address)
+ {
+ require(false, stub_error);
+ contractAddress;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ function sponsoringEnabled(address contractAddress)
+ public
+ view
+ returns (bool)
+ {
+ require(false, stub_error);
+ contractAddress;
+ dummy;
+ return false;
+ }
+
+ function toggleSponsoring(address contractAddress, bool enabled) public {
+ require(false, stub_error);
+ contractAddress;
+ enabled;
+ dummy = 0;
+ }
+
+ function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
+ public
+ {
+ require(false, stub_error);
+ contractAddress;
+ rateLimit;
+ dummy = 0;
+ }
+
+ function allowed(address contractAddress, address user)
+ public
+ view
+ returns (bool)
+ {
+ require(false, stub_error);
+ contractAddress;
+ user;
+ dummy;
+ return false;
+ }
+
+ function allowlistEnabled(address contractAddress)
+ public
+ view
+ returns (bool)
+ {
+ require(false, stub_error);
+ contractAddress;
+ dummy;
+ return false;
+ }
- function contractOwner(address contract_address) public view returns (address) {
- require(false, stub_error);
- contract_address;
- return _dummy_addr;
- }
-
- function sponsoringEnabled(address contract_address) public view returns (bool) {
- require(false, stub_error);
- contract_address;
- _dummmy;
- return false;
- }
-
- function toggleSponsoring(address contract_address, bool enabled) public {
- require(false, stub_error);
- contract_address;
- enabled;
- _dummmy = 0;
- }
-
- function toggleAllowlist(address contract_address, bool enabled) public {
- require(false, stub_error);
- contract_address;
- enabled;
- _dummmy = 0;
- }
-
- function toggleAllowed(address contract_address, address user, bool allowed) public {
- require(false, stub_error);
- contract_address;
- user;
- allowed;
- _dummmy = 0;
- }
-}
\ No newline at end of file
+ function toggleAllowlist(address contractAddress, bool enabled) public {
+ require(false, stub_error);
+ contractAddress;
+ enabled;
+ dummy = 0;
+ }
+
+ function toggleAllowed(
+ address contractAddress,
+ address user,
+ bool allowed
+ ) public {
+ require(false, stub_error);
+ contractAddress;
+ user;
+ allowed;
+ dummy = 0;
+ }
+}
pallets/nft/src/eth/erc.rsdiffbeforeafterboth1use core::char::{decode_utf16, REPLACEMENT_CHARACTER};2use evm_coder::{ToLog, execution::Result, solidity, solidity_interface, types::*};3use nft_data_structs::{CreateItemData, CreateNftData};4use core::convert::TryInto;5use crate::{6 Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList,7 ItemListIndex,8};9use frame_support::storage::{StorageMap, StorageDoubleMap};10use pallet_evm::AddressMapping;11use super::account::CrossAccountId;12use sp_std::{vec, vec::Vec};1314#[solidity_interface(name = "ERC165")]15impl<T: Config> CollectionHandle<T> {16 fn supports_interface(&self, interface_id: bytes4) -> Result<bool> {17 Ok(match self.mode {18 CollectionMode::Fungible(_) => UniqueFungibleCall::supports_interface(interface_id),19 CollectionMode::NFT => UniqueNFTCall::supports_interface(interface_id),20 _ => false,21 })22 }23}2425#[solidity_interface(name = "InlineNameSymbol")]26impl<T: Config> CollectionHandle<T> {27 fn name(&self) -> Result<string> {28 Ok(decode_utf16(self.name.iter().copied())29 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))30 .collect::<string>())31 }3233 fn symbol(&self) -> Result<string> {34 Ok(string::from_utf8_lossy(&self.token_prefix).into())35 }36}3738#[solidity_interface(name = "InlineTotalSupply")]39impl<T: Config> CollectionHandle<T> {40 fn total_supply(&self) -> Result<uint256> {41 // TODO: we do not track total amount of all tokens42 Ok(0.into())43 }44}4546#[solidity_interface(name = "ERC721Metadata", inline_is(InlineNameSymbol))]47impl<T: Config> CollectionHandle<T> {48 #[solidity(rename_selector = "tokenURI")]49 fn token_uri(&self, token_id: uint256) -> Result<string> {50 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;51 Ok(string::from_utf8_lossy(52 &<NftItemList<T>>::get(self.id, token_id)53 .ok_or("token not found")?54 .const_data,55 )56 .into())57 }58}5960#[solidity_interface(name = "ERC721Enumerable", inline_is(InlineTotalSupply))]61impl<T: Config> CollectionHandle<T> {62 fn token_by_index(&self, index: uint256) -> Result<uint256> {63 Ok(index)64 }6566 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {67 // TODO: Not implemetable68 Err("not implemented".into())69 }70}7172#[derive(ToLog)]73pub enum ERC721Events {74 Transfer {75 #[indexed]76 from: address,77 #[indexed]78 to: address,79 #[indexed]80 token_id: uint256,81 },82 Approval {83 #[indexed]84 owner: address,85 #[indexed]86 approved: address,87 #[indexed]88 token_id: uint256,89 },90 #[allow(dead_code)]91 ApprovalForAll {92 #[indexed]93 owner: address,94 #[indexed]95 operator: address,96 approved: bool,97 },98}99100#[solidity_interface(name = "ERC721", is(ERC165), events(ERC721Events))]101impl<T: Config> CollectionHandle<T> {102 #[solidity(rename_selector = "balanceOf")]103 fn balance_of_nft(&self, owner: address) -> Result<uint256> {104 let owner = T::EvmAddressMapping::into_account_id(owner);105 let balance = <Balance<T>>::get(self.id, owner);106 Ok(balance.into())107 }108 fn owner_of(&self, token_id: uint256) -> Result<address> {109 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;110 let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;111 Ok(*token.owner.as_eth())112 }113 fn safe_transfer_from_with_data(114 &mut self,115 _from: address,116 _to: address,117 _token_id: uint256,118 _data: bytes,119 _value: value,120 ) -> Result<void> {121 // TODO: Not implemetable122 Err("not implemented".into())123 }124 fn safe_transfer_from(125 &mut self,126 _from: address,127 _to: address,128 _token_id: uint256,129 _value: value,130 ) -> Result<void> {131 // TODO: Not implemetable132 Err("not implemented".into())133 }134135 fn transfer_from(136 &mut self,137 caller: caller,138 from: address,139 to: address,140 token_id: uint256,141 _value: value,142 ) -> Result<void> {143 let caller = T::CrossAccountId::from_eth(caller);144 let from = T::CrossAccountId::from_eth(from);145 let to = T::CrossAccountId::from_eth(to);146 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;147148 <Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)149 .map_err(|_| "transferFrom error")?;150 Ok(())151 }152153 fn approve(154 &mut self,155 caller: caller,156 approved: address,157 token_id: uint256,158 _value: value,159 ) -> Result<void> {160 let caller = T::CrossAccountId::from_eth(caller);161 let approved = T::CrossAccountId::from_eth(approved);162 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;163164 <Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)165 .map_err(|_| "approve internal")?;166 Ok(())167 }168169 fn set_approval_for_all(170 &mut self,171 _caller: caller,172 _operator: address,173 _approved: bool,174 ) -> Result<void> {175 // TODO: Not implemetable176 Err("not implemented".into())177 }178179 fn get_approved(&self, _token_id: uint256) -> Result<address> {180 // TODO: Not implemetable181 Err("not implemented".into())182 }183184 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {185 // TODO: Not implemetable186 Err("not implemented".into())187 }188}189190#[solidity_interface(name = "ERC721Burnable")]191impl<T: Config> CollectionHandle<T> {192 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {193 let caller = T::CrossAccountId::from_eth(caller);194 let token_id = token_id.try_into().map_err(|_| "amount overflow")?;195196 <Module<T>>::burn_item_internal(&caller, &self, token_id, 1).map_err(|_| "burn error")?;197 Ok(())198 }199}200201#[derive(ToLog)]202pub enum ERC721MintableEvents {203 #[allow(dead_code)]204 MintingFinished {},205}206207#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]208impl<T: Config> CollectionHandle<T> {209 fn minting_finished(&self) -> Result<bool> {210 Ok(false)211 }212213 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {214 let caller = T::CrossAccountId::from_eth(caller);215 let to = T::CrossAccountId::from_eth(to);216 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;217 if <ItemListIndex>::get(self.id)218 .checked_add(1)219 .ok_or("item id overflow")?220 != token_id221 {222 return Err("item id should be next".into());223 }224225 <Module<T>>::create_item_internal(226 &caller,227 &self,228 &to,229 CreateItemData::NFT(CreateNftData {230 const_data: vec![].try_into().unwrap(),231 variable_data: vec![].try_into().unwrap(),232 }),233 )234 .map_err(|_| "mint error")?;235 Ok(true)236 }237238 #[solidity(rename_selector = "mintWithTokenURI")]239 fn mint_with_token_uri(240 &mut self,241 caller: caller,242 to: address,243 token_id: uint256,244 token_uri: string,245 ) -> Result<bool> {246 let caller = T::CrossAccountId::from_eth(caller);247 let to = T::CrossAccountId::from_eth(to);248 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;249 if <ItemListIndex>::get(self.id)250 .checked_add(1)251 .ok_or("item id overflow")?252 != token_id253 {254 return Err("item id should be next".into());255 }256257 <Module<T>>::create_item_internal(258 &caller,259 &self,260 &to,261 CreateItemData::NFT(CreateNftData {262 const_data: Vec::<u8>::from(token_uri)263 .try_into()264 .map_err(|_| "token uri is too long")?,265 variable_data: vec![].try_into().unwrap(),266 }),267 )268 .map_err(|_| "mint error")?;269 Ok(true)270 }271272 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {273 Err("not implementable".into())274 }275}276277#[solidity_interface(name = "ERC721UniqueExtensions")]278impl<T: Config> CollectionHandle<T> {279 #[solidity(rename_selector = "transfer")]280 fn transfer_nft(281 &mut self,282 caller: caller,283 to: address,284 token_id: uint256,285 _value: value,286 ) -> Result<void> {287 let caller = T::CrossAccountId::from_eth(caller);288 let to = T::CrossAccountId::from_eth(to);289 let token_id = token_id.try_into().map_err(|_| "amount overflow")?;290291 <Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)292 .map_err(|_| "transfer error")?;293 Ok(())294 }295296 fn next_token_id(&self) -> Result<uint256> {297 Ok(ItemListIndex::get(self.id)298 .checked_add(1)299 .ok_or("item id overflow")?300 .into())301 }302}303304#[solidity_interface(305 name = "UniqueNFT",306 is(307 ERC165,308 ERC721,309 ERC721Metadata,310 ERC721Enumerable,311 ERC721UniqueExtensions,312 ERC721Mintable,313 ERC721Burnable,314 )315)]316impl<T: Config> CollectionHandle<T> {}317318#[derive(ToLog)]319pub enum ERC20Events {320 Transfer {321 #[indexed]322 from: address,323 #[indexed]324 to: address,325 value: uint256,326 },327 Approval {328 #[indexed]329 owner: address,330 #[indexed]331 spender: address,332 value: uint256,333 },334}335336#[solidity_interface(337 name = "ERC20",338 inline_is(InlineNameSymbol, InlineTotalSupply),339 events(ERC20Events)340)]341impl<T: Config> CollectionHandle<T> {342 fn decimals(&self) -> Result<uint8> {343 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {344 *decimals345 } else {346 unreachable!()347 })348 }349 fn balance_of(&self, owner: address) -> Result<uint256> {350 let owner = T::EvmAddressMapping::into_account_id(owner);351 let balance = <Balance<T>>::get(self.id, owner);352 Ok(balance.into())353 }354 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {355 let caller = T::CrossAccountId::from_eth(caller);356 let to = T::CrossAccountId::from_eth(to);357 let amount = amount.try_into().map_err(|_| "amount overflow")?;358359 <Module<T>>::transfer_internal(&caller, &to, self, 1, amount)360 .map_err(|_| "transfer error")?;361 Ok(true)362 }363 #[solidity(rename_selector = "transferFrom")]364 fn transfer_from_fungible(365 &mut self,366 caller: caller,367 from: address,368 to: address,369 amount: uint256,370 ) -> Result<bool> {371 let caller = T::CrossAccountId::from_eth(caller);372 let from = T::CrossAccountId::from_eth(from);373 let to = T::CrossAccountId::from_eth(to);374 let amount = amount.try_into().map_err(|_| "amount overflow")?;375376 <Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)377 .map_err(|_| "transferFrom error")?;378 Ok(true)379 }380 #[solidity(rename_selector = "approve")]381 fn approve_fungible(382 &mut self,383 caller: caller,384 spender: address,385 amount: uint256,386 ) -> Result<bool> {387 let caller = T::CrossAccountId::from_eth(caller);388 let spender = T::CrossAccountId::from_eth(spender);389 let amount = amount.try_into().map_err(|_| "amount overflow")?;390391 <Module<T>>::approve_internal(&caller, &spender, self, 1, amount)392 .map_err(|_| "approve internal")?;393 Ok(true)394 }395 fn allowance(&self, owner: address, spender: address) -> Result<uint256> {396 let owner = T::CrossAccountId::from_eth(owner);397 let spender = T::CrossAccountId::from_eth(spender);398399 Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())400 }401}402403#[solidity_interface(name = "UniqueFungible", is(ERC165, ERC20))]404impl<T: Config> CollectionHandle<T> {}405406macro_rules! generate_code {407 ($name:ident, $decl:ident, $is_impl:literal) => {408 #[test]409 #[ignore]410 fn $name() {411 use sp_std::collections::btree_set::BTreeSet;412 let mut out = BTreeSet::new();413 $decl::generate_solidity_interface(&mut out, $is_impl);414 println!("=== SNIP START ===");415 println!("// SPDX-License-Identifier: OTHER");416 println!("// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::{} --exact --nocapture --ignored`", stringify!(name));417 println!();418 println!("pragma solidity >=0.8.0 <0.9.0;");419 println!();420 for b in out {421 println!("{}", b);422 }423 println!("=== SNIP END ===");424 }425 };426}427428// Not a tests, but code generators429generate_code!(nft_impl, UniqueNFTCall, true);430generate_code!(nft_iface, UniqueNFTCall, false);431432generate_code!(fungible_impl, UniqueFungibleCall, true);433generate_code!(fungible_iface, UniqueFungibleCall, false);1use core::char::{decode_utf16, REPLACEMENT_CHARACTER};2use evm_coder::{ToLog, execution::Result, generate_stubgen, solidity, solidity_interface, types::*};3use nft_data_structs::{CreateItemData, CreateNftData};4use core::convert::TryInto;5use crate::{6 Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList,7 ItemListIndex,8};9use frame_support::storage::{StorageMap, StorageDoubleMap};10use pallet_evm::AddressMapping;11use super::account::CrossAccountId;12use sp_std::{vec, vec::Vec};1314#[solidity_interface(name = "ERC165")]15impl<T: Config> CollectionHandle<T> {16 fn supports_interface(&self, interface_id: bytes4) -> Result<bool> {17 Ok(match self.mode {18 CollectionMode::Fungible(_) => UniqueFungibleCall::supports_interface(interface_id),19 CollectionMode::NFT => UniqueNFTCall::supports_interface(interface_id),20 _ => false,21 })22 }23}2425#[solidity_interface(name = "InlineNameSymbol")]26impl<T: Config> CollectionHandle<T> {27 fn name(&self) -> Result<string> {28 Ok(decode_utf16(self.name.iter().copied())29 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))30 .collect::<string>())31 }3233 fn symbol(&self) -> Result<string> {34 Ok(string::from_utf8_lossy(&self.token_prefix).into())35 }36}3738#[solidity_interface(name = "InlineTotalSupply")]39impl<T: Config> CollectionHandle<T> {40 fn total_supply(&self) -> Result<uint256> {41 // TODO: we do not track total amount of all tokens42 Ok(0.into())43 }44}4546#[solidity_interface(name = "ERC721Metadata", inline_is(InlineNameSymbol))]47impl<T: Config> CollectionHandle<T> {48 #[solidity(rename_selector = "tokenURI")]49 fn token_uri(&self, token_id: uint256) -> Result<string> {50 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;51 Ok(string::from_utf8_lossy(52 &<NftItemList<T>>::get(self.id, token_id)53 .ok_or("token not found")?54 .const_data,55 )56 .into())57 }58}5960#[solidity_interface(name = "ERC721Enumerable", inline_is(InlineTotalSupply))]61impl<T: Config> CollectionHandle<T> {62 fn token_by_index(&self, index: uint256) -> Result<uint256> {63 Ok(index)64 }6566 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {67 // TODO: Not implemetable68 Err("not implemented".into())69 }70}7172#[derive(ToLog)]73pub enum ERC721Events {74 Transfer {75 #[indexed]76 from: address,77 #[indexed]78 to: address,79 #[indexed]80 token_id: uint256,81 },82 Approval {83 #[indexed]84 owner: address,85 #[indexed]86 approved: address,87 #[indexed]88 token_id: uint256,89 },90 #[allow(dead_code)]91 ApprovalForAll {92 #[indexed]93 owner: address,94 #[indexed]95 operator: address,96 approved: bool,97 },98}99100#[solidity_interface(name = "ERC721", is(ERC165), events(ERC721Events))]101impl<T: Config> CollectionHandle<T> {102 #[solidity(rename_selector = "balanceOf")]103 fn balance_of_nft(&self, owner: address) -> Result<uint256> {104 let owner = T::EvmAddressMapping::into_account_id(owner);105 let balance = <Balance<T>>::get(self.id, owner);106 Ok(balance.into())107 }108 fn owner_of(&self, token_id: uint256) -> Result<address> {109 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;110 let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;111 Ok(*token.owner.as_eth())112 }113 fn safe_transfer_from_with_data(114 &mut self,115 _from: address,116 _to: address,117 _token_id: uint256,118 _data: bytes,119 _value: value,120 ) -> Result<void> {121 // TODO: Not implemetable122 Err("not implemented".into())123 }124 fn safe_transfer_from(125 &mut self,126 _from: address,127 _to: address,128 _token_id: uint256,129 _value: value,130 ) -> Result<void> {131 // TODO: Not implemetable132 Err("not implemented".into())133 }134135 fn transfer_from(136 &mut self,137 caller: caller,138 from: address,139 to: address,140 token_id: uint256,141 _value: value,142 ) -> Result<void> {143 let caller = T::CrossAccountId::from_eth(caller);144 let from = T::CrossAccountId::from_eth(from);145 let to = T::CrossAccountId::from_eth(to);146 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;147148 <Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)149 .map_err(|_| "transferFrom error")?;150 Ok(())151 }152153 fn approve(154 &mut self,155 caller: caller,156 approved: address,157 token_id: uint256,158 _value: value,159 ) -> Result<void> {160 let caller = T::CrossAccountId::from_eth(caller);161 let approved = T::CrossAccountId::from_eth(approved);162 let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;163164 <Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)165 .map_err(|_| "approve internal")?;166 Ok(())167 }168169 fn set_approval_for_all(170 &mut self,171 _caller: caller,172 _operator: address,173 _approved: bool,174 ) -> Result<void> {175 // TODO: Not implemetable176 Err("not implemented".into())177 }178179 fn get_approved(&self, _token_id: uint256) -> Result<address> {180 // TODO: Not implemetable181 Err("not implemented".into())182 }183184 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {185 // TODO: Not implemetable186 Err("not implemented".into())187 }188}189190#[solidity_interface(name = "ERC721Burnable")]191impl<T: Config> CollectionHandle<T> {192 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {193 let caller = T::CrossAccountId::from_eth(caller);194 let token_id = token_id.try_into().map_err(|_| "amount overflow")?;195196 <Module<T>>::burn_item_internal(&caller, &self, token_id, 1).map_err(|_| "burn error")?;197 Ok(())198 }199}200201#[derive(ToLog)]202pub enum ERC721MintableEvents {203 #[allow(dead_code)]204 MintingFinished {},205}206207#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]208impl<T: Config> CollectionHandle<T> {209 fn minting_finished(&self) -> Result<bool> {210 Ok(false)211 }212213 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {214 let caller = T::CrossAccountId::from_eth(caller);215 let to = T::CrossAccountId::from_eth(to);216 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;217 if <ItemListIndex>::get(self.id)218 .checked_add(1)219 .ok_or("item id overflow")?220 != token_id221 {222 return Err("item id should be next".into());223 }224225 <Module<T>>::create_item_internal(226 &caller,227 &self,228 &to,229 CreateItemData::NFT(CreateNftData {230 const_data: vec![].try_into().unwrap(),231 variable_data: vec![].try_into().unwrap(),232 }),233 )234 .map_err(|_| "mint error")?;235 Ok(true)236 }237238 #[solidity(rename_selector = "mintWithTokenURI")]239 fn mint_with_token_uri(240 &mut self,241 caller: caller,242 to: address,243 token_id: uint256,244 token_uri: string,245 ) -> Result<bool> {246 let caller = T::CrossAccountId::from_eth(caller);247 let to = T::CrossAccountId::from_eth(to);248 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;249 if <ItemListIndex>::get(self.id)250 .checked_add(1)251 .ok_or("item id overflow")?252 != token_id253 {254 return Err("item id should be next".into());255 }256257 <Module<T>>::create_item_internal(258 &caller,259 &self,260 &to,261 CreateItemData::NFT(CreateNftData {262 const_data: Vec::<u8>::from(token_uri)263 .try_into()264 .map_err(|_| "token uri is too long")?,265 variable_data: vec![].try_into().unwrap(),266 }),267 )268 .map_err(|_| "mint error")?;269 Ok(true)270 }271272 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {273 Err("not implementable".into())274 }275}276277#[solidity_interface(name = "ERC721UniqueExtensions")]278impl<T: Config> CollectionHandle<T> {279 #[solidity(rename_selector = "transfer")]280 fn transfer_nft(281 &mut self,282 caller: caller,283 to: address,284 token_id: uint256,285 _value: value,286 ) -> Result<void> {287 let caller = T::CrossAccountId::from_eth(caller);288 let to = T::CrossAccountId::from_eth(to);289 let token_id = token_id.try_into().map_err(|_| "amount overflow")?;290291 <Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)292 .map_err(|_| "transfer error")?;293 Ok(())294 }295296 fn next_token_id(&self) -> Result<uint256> {297 Ok(ItemListIndex::get(self.id)298 .checked_add(1)299 .ok_or("item id overflow")?300 .into())301 }302}303304#[solidity_interface(305 name = "UniqueNFT",306 is(307 ERC165,308 ERC721,309 ERC721Metadata,310 ERC721Enumerable,311 ERC721UniqueExtensions,312 ERC721Mintable,313 ERC721Burnable,314 )315)]316impl<T: Config> CollectionHandle<T> {}317318#[derive(ToLog)]319pub enum ERC20Events {320 Transfer {321 #[indexed]322 from: address,323 #[indexed]324 to: address,325 value: uint256,326 },327 Approval {328 #[indexed]329 owner: address,330 #[indexed]331 spender: address,332 value: uint256,333 },334}335336#[solidity_interface(337 name = "ERC20",338 inline_is(InlineNameSymbol, InlineTotalSupply),339 events(ERC20Events)340)]341impl<T: Config> CollectionHandle<T> {342 fn decimals(&self) -> Result<uint8> {343 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {344 *decimals345 } else {346 unreachable!()347 })348 }349 fn balance_of(&self, owner: address) -> Result<uint256> {350 let owner = T::EvmAddressMapping::into_account_id(owner);351 let balance = <Balance<T>>::get(self.id, owner);352 Ok(balance.into())353 }354 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {355 let caller = T::CrossAccountId::from_eth(caller);356 let to = T::CrossAccountId::from_eth(to);357 let amount = amount.try_into().map_err(|_| "amount overflow")?;358359 <Module<T>>::transfer_internal(&caller, &to, self, 1, amount)360 .map_err(|_| "transfer error")?;361 Ok(true)362 }363 #[solidity(rename_selector = "transferFrom")]364 fn transfer_from_fungible(365 &mut self,366 caller: caller,367 from: address,368 to: address,369 amount: uint256,370 ) -> Result<bool> {371 let caller = T::CrossAccountId::from_eth(caller);372 let from = T::CrossAccountId::from_eth(from);373 let to = T::CrossAccountId::from_eth(to);374 let amount = amount.try_into().map_err(|_| "amount overflow")?;375376 <Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)377 .map_err(|_| "transferFrom error")?;378 Ok(true)379 }380 #[solidity(rename_selector = "approve")]381 fn approve_fungible(382 &mut self,383 caller: caller,384 spender: address,385 amount: uint256,386 ) -> Result<bool> {387 let caller = T::CrossAccountId::from_eth(caller);388 let spender = T::CrossAccountId::from_eth(spender);389 let amount = amount.try_into().map_err(|_| "amount overflow")?;390391 <Module<T>>::approve_internal(&caller, &spender, self, 1, amount)392 .map_err(|_| "approve internal")?;393 Ok(true)394 }395 fn allowance(&self, owner: address, spender: address) -> Result<uint256> {396 let owner = T::CrossAccountId::from_eth(owner);397 let spender = T::CrossAccountId::from_eth(spender);398399 Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())400 }401}402403#[solidity_interface(name = "UniqueFungible", is(ERC165, ERC20))]404impl<T: Config> CollectionHandle<T> {}405406// Not a tests, but code generators407generate_stubgen!(nft_impl, UniqueNFTCall, true);408generate_stubgen!(nft_iface, UniqueNFTCall, false);409410generate_stubgen!(fungible_impl, UniqueFungibleCall, true);411generate_stubgen!(fungible_iface, UniqueFungibleCall, false);pallets/nft/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/mod.rs
+++ b/pallets/nft/src/eth/mod.rs
@@ -96,10 +96,14 @@
.and_then(<CollectionById<T>>::get)
.map(|collection| {
match collection.mode {
- CollectionMode::NFT => include_bytes!("stubs/ERC721.bin") as &[u8],
- CollectionMode::Fungible(_) => include_bytes!("stubs/ERC20.bin") as &[u8],
- CollectionMode::ReFungible => include_bytes!("stubs/ERC1633.bin") as &[u8],
- CollectionMode::Invalid => include_bytes!("stubs/Invalid.bin") as &[u8],
+ CollectionMode::NFT => include_bytes!("stubs/UniqueNFT.raw") as &[u8],
+ CollectionMode::Fungible(_) => {
+ include_bytes!("stubs/UniqueFungible.raw") as &[u8]
+ }
+ CollectionMode::ReFungible => {
+ include_bytes!("stubs/UniqueRefungible.raw") as &[u8]
+ }
+ CollectionMode::Invalid => include_bytes!("stubs/UniqueInvalid.raw") as &[u8],
}
.to_owned()
})
pallets/nft/src/eth/stubs/ERC1633.bindiffbeforeafterboth--- a/pallets/nft/src/eth/stubs/ERC1633.bin
+++ /dev/null
@@ -1 +0,0 @@
-TODO
\ No newline at end of file
pallets/nft/src/eth/stubs/ERC20.bindiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/ERC20.soldiffbeforeafterboth--- a/pallets/nft/src/eth/stubs/ERC20.sol
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: OTHER
-// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::name --exact --nocapture --ignored`
-
-pragma solidity >=0.8.0 <0.9.0;
-
-// Common stubs holder
-contract Dummy {
- uint8 dummy;
- string stub_error = "this contract is implemented in native";
-}
-
-// Inline
-contract ERC20Events {
- event Transfer(address from, address to, uint256 value);
- event Approval(address owner, address spender, uint256 value);
-}
-
-// Inline
-contract InlineNameSymbol is Dummy {
- function name() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
- function symbol() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
-}
-
-// Inline
-contract InlineTotalSupply is Dummy {
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-contract ERC165 is Dummy {
- function supportsInterface(uint32 interfaceId) public view returns (bool) {
- require(false, stub_error);
- interfaceId;
- dummy;
- return false;
- }
-}
-
-contract ERC20 is Dummy, InlineNameSymbol, InlineTotalSupply, ERC20Events {
- function decimals() public view returns (uint8) {
- require(false, stub_error);
- dummy;
- return 0;
- }
- function balanceOf(address owner) public view returns (uint256) {
- require(false, stub_error);
- owner;
- dummy;
- return 0;
- }
- function transfer(address to, uint256 amount) public returns (bool) {
- require(false, stub_error);
- to;
- amount;
- dummy = 0;
- return false;
- }
- function transferFrom(address from, address to, uint256 amount) public returns (bool) {
- require(false, stub_error);
- from;
- to;
- amount;
- dummy = 0;
- return false;
- }
- function approve(address spender, uint256 amount) public returns (bool) {
- require(false, stub_error);
- spender;
- amount;
- dummy = 0;
- return false;
- }
- function allowance(address owner, address spender) public view returns (uint256) {
- require(false, stub_error);
- owner;
- spender;
- dummy;
- return 0;
- }
-}
-
-contract UniqueFungible is Dummy, ERC165, ERC20 {
-}
\ No newline at end of file
pallets/nft/src/eth/stubs/ERC721.bindiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/ERC721.soldiffbeforeafterboth--- a/pallets/nft/src/eth/stubs/ERC721.sol
+++ /dev/null
@@ -1,194 +0,0 @@
-// SPDX-License-Identifier: OTHER
-// This code is automatically generated with `cargo test --package pallet-nft -- eth::erc::name --exact --nocapture --ignored`
-
-pragma solidity >=0.8.0 <0.9.0;
-
-// Common stubs holder
-contract Dummy {
- uint8 dummy;
- string stub_error = "this contract is implemented in native";
-}
-
-// Inline
-contract ERC721Events {
- event Transfer(address from, address to, uint256 tokenId);
- event Approval(address owner, address approved, uint256 tokenId);
- event ApprovalForAll(address owner, address operator, bool approved);
-}
-
-// Inline
-contract ERC721MintableEvents {
- event MintingFinished();
-}
-
-// Inline
-contract InlineNameSymbol is Dummy {
- function name() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
- function symbol() public view returns (string memory) {
- require(false, stub_error);
- dummy;
- return "";
- }
-}
-
-// Inline
-contract InlineTotalSupply is Dummy {
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-contract ERC165 is Dummy {
- function supportsInterface(uint32 interfaceId) public view returns (bool) {
- require(false, stub_error);
- interfaceId;
- dummy;
- return false;
- }
-}
-
-contract ERC721 is Dummy, ERC165, ERC721Events {
- function balanceOf(address owner) public view returns (uint256) {
- require(false, stub_error);
- owner;
- dummy;
- return 0;
- }
- function ownerOf(uint256 tokenId) public view returns (address) {
- require(false, stub_error);
- tokenId;
- dummy;
- return 0x0000000000000000000000000000000000000000;
- }
- function safeTransferFromWithData(address from, address to, uint256 tokenId, bytes memory data) public {
- require(false, stub_error);
- from;
- to;
- tokenId;
- data;
- dummy = 0;
- }
- function safeTransferFrom(address from, address to, uint256 tokenId) public {
- require(false, stub_error);
- from;
- to;
- tokenId;
- dummy = 0;
- }
- function transferFrom(address from, address to, uint256 tokenId) public {
- require(false, stub_error);
- from;
- to;
- tokenId;
- dummy = 0;
- }
- function approve(address approved, uint256 tokenId) public {
- require(false, stub_error);
- approved;
- tokenId;
- dummy = 0;
- }
- function setApprovalForAll(address operator, bool approved) public {
- require(false, stub_error);
- operator;
- approved;
- dummy = 0;
- }
- function getApproved(uint256 tokenId) public view returns (address) {
- require(false, stub_error);
- tokenId;
- dummy;
- return 0x0000000000000000000000000000000000000000;
- }
- function isApprovedForAll(address owner, address operator) public view returns (address) {
- require(false, stub_error);
- owner;
- operator;
- dummy;
- return 0x0000000000000000000000000000000000000000;
- }
-}
-
-contract ERC721Burnable is Dummy {
- function burn(uint256 tokenId) public {
- require(false, stub_error);
- tokenId;
- dummy = 0;
- }
-}
-
-contract ERC721Enumerable is Dummy, InlineTotalSupply {
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
- function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-}
-
-contract ERC721Metadata is Dummy, InlineNameSymbol {
- function tokenURI(uint256 tokenId) public view returns (string memory) {
- require(false, stub_error);
- tokenId;
- dummy;
- return "";
- }
-}
-
-contract ERC721Mintable is Dummy, ERC721MintableEvents {
- function mintingFinished() public view returns (bool) {
- require(false, stub_error);
- dummy;
- return false;
- }
- function mint(address to, uint256 tokenId) public returns (bool) {
- require(false, stub_error);
- to;
- tokenId;
- dummy = 0;
- return false;
- }
- function mintWithTokenURI(address to, uint256 tokenId, string memory tokenUri) public returns (bool) {
- require(false, stub_error);
- to;
- tokenId;
- tokenUri;
- dummy = 0;
- return false;
- }
- function finishMinting() public returns (bool) {
- require(false, stub_error);
- dummy = 0;
- return false;
- }
-}
-
-contract ERC721UniqueExtensions is Dummy {
- function transfer(address to, uint256 tokenId) public {
- require(false, stub_error);
- to;
- tokenId;
- dummy = 0;
- }
- function nextTokenId() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-contract UniqueNFT is Dummy, ERC165, ERC721, ERC721Metadata, ERC721Enumerable, ERC721UniqueExtensions, ERC721Mintable, ERC721Burnable {
-}
\ No newline at end of file
pallets/nft/src/eth/stubs/Invalid.bindiffbeforeafterboth--- a/pallets/nft/src/eth/stubs/Invalid.bin
+++ /dev/null
@@ -1 +0,0 @@
-TODO
\ No newline at end of file
pallets/nft/src/eth/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/UniqueFungible.soldiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueFungible.sol
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+ uint8 dummy;
+ string stub_error = "this contract is implemented in native";
+}
+
+// Inline
+contract ERC20Events {
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+}
+
+// Inline
+contract InlineNameSymbol is Dummy {
+ function name() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+
+ function symbol() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+}
+
+// Inline
+contract InlineTotalSupply is Dummy {
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+}
+
+contract ERC165 is Dummy {
+ function supportsInterface(uint32 interfaceId) public view returns (bool) {
+ require(false, stub_error);
+ interfaceId;
+ dummy;
+ return false;
+ }
+}
+
+contract ERC20 is Dummy, InlineNameSymbol, InlineTotalSupply, ERC20Events {
+ function decimals() public view returns (uint8) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+
+ function balanceOf(address owner) public view returns (uint256) {
+ require(false, stub_error);
+ owner;
+ dummy;
+ return 0;
+ }
+
+ function transfer(address to, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ to;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ function transferFrom(
+ address from,
+ address to,
+ uint256 amount
+ ) public returns (bool) {
+ require(false, stub_error);
+ from;
+ to;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ function approve(address spender, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ spender;
+ amount;
+ dummy = 0;
+ return false;
+ }
+
+ function allowance(address owner, address spender)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ spender;
+ dummy;
+ return 0;
+ }
+}
+
+contract UniqueFungible is Dummy, ERC165, ERC20 {}
pallets/nft/src/eth/stubs/UniqueInvalid.rawdiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueInvalid.raw
@@ -0,0 +1 @@
+TODO
\ No newline at end of file
pallets/nft/src/eth/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/UniqueNFT.soldiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueNFT.sol
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+ uint8 dummy;
+ string stub_error = "this contract is implemented in native";
+}
+
+// Inline
+contract ERC721Events {
+ event Transfer(
+ address indexed from,
+ address indexed to,
+ uint256 indexed tokenId
+ );
+ event Approval(
+ address indexed owner,
+ address indexed approved,
+ uint256 indexed tokenId
+ );
+ event ApprovalForAll(
+ address indexed owner,
+ address indexed operator,
+ bool approved
+ );
+}
+
+// Inline
+contract ERC721MintableEvents {
+ event MintingFinished();
+}
+
+// Inline
+contract InlineNameSymbol is Dummy {
+ function name() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+
+ function symbol() public view returns (string memory) {
+ require(false, stub_error);
+ dummy;
+ return "";
+ }
+}
+
+// Inline
+contract InlineTotalSupply is Dummy {
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+}
+
+contract ERC165 is Dummy {
+ function supportsInterface(uint32 interfaceId) public view returns (bool) {
+ require(false, stub_error);
+ interfaceId;
+ dummy;
+ return false;
+ }
+}
+
+contract ERC721 is Dummy, ERC165, ERC721Events {
+ function balanceOf(address owner) public view returns (uint256) {
+ require(false, stub_error);
+ owner;
+ dummy;
+ return 0;
+ }
+
+ function ownerOf(uint256 tokenId) public view returns (address) {
+ require(false, stub_error);
+ tokenId;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ function safeTransferFromWithData(
+ address from,
+ address to,
+ uint256 tokenId,
+ bytes memory data
+ ) public {
+ require(false, stub_error);
+ from;
+ to;
+ tokenId;
+ data;
+ dummy = 0;
+ }
+
+ function safeTransferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
+ require(false, stub_error);
+ from;
+ to;
+ tokenId;
+ dummy = 0;
+ }
+
+ function transferFrom(
+ address from,
+ address to,
+ uint256 tokenId
+ ) public {
+ require(false, stub_error);
+ from;
+ to;
+ tokenId;
+ dummy = 0;
+ }
+
+ function approve(address approved, uint256 tokenId) public {
+ require(false, stub_error);
+ approved;
+ tokenId;
+ dummy = 0;
+ }
+
+ function setApprovalForAll(address operator, bool approved) public {
+ require(false, stub_error);
+ operator;
+ approved;
+ dummy = 0;
+ }
+
+ function getApproved(uint256 tokenId) public view returns (address) {
+ require(false, stub_error);
+ tokenId;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ function isApprovedForAll(address owner, address operator)
+ public
+ view
+ returns (address)
+ {
+ require(false, stub_error);
+ owner;
+ operator;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+}
+
+contract ERC721Burnable is Dummy {
+ function burn(uint256 tokenId) public {
+ require(false, stub_error);
+ tokenId;
+ dummy = 0;
+ }
+}
+
+contract ERC721Enumerable is Dummy, InlineTotalSupply {
+ function tokenByIndex(uint256 index) public view returns (uint256) {
+ require(false, stub_error);
+ index;
+ dummy;
+ return 0;
+ }
+
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ index;
+ dummy;
+ return 0;
+ }
+}
+
+contract ERC721Metadata is Dummy, InlineNameSymbol {
+ function tokenURI(uint256 tokenId) public view returns (string memory) {
+ require(false, stub_error);
+ tokenId;
+ dummy;
+ return "";
+ }
+}
+
+contract ERC721Mintable is Dummy, ERC721MintableEvents {
+ function mintingFinished() public view returns (bool) {
+ require(false, stub_error);
+ dummy;
+ return false;
+ }
+
+ function mint(address to, uint256 tokenId) public returns (bool) {
+ require(false, stub_error);
+ to;
+ tokenId;
+ dummy = 0;
+ return false;
+ }
+
+ function mintWithTokenURI(
+ address to,
+ uint256 tokenId,
+ string memory tokenUri
+ ) public returns (bool) {
+ require(false, stub_error);
+ to;
+ tokenId;
+ tokenUri;
+ dummy = 0;
+ return false;
+ }
+
+ function finishMinting() public returns (bool) {
+ require(false, stub_error);
+ dummy = 0;
+ return false;
+ }
+}
+
+contract ERC721UniqueExtensions is Dummy {
+ function transfer(address to, uint256 tokenId) public {
+ require(false, stub_error);
+ to;
+ tokenId;
+ dummy = 0;
+ }
+
+ function nextTokenId() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+}
+
+contract UniqueNFT is
+ Dummy,
+ ERC165,
+ ERC721,
+ ERC721Metadata,
+ ERC721Enumerable,
+ ERC721UniqueExtensions,
+ ERC721Mintable,
+ ERC721Burnable
+{}
pallets/nft/src/eth/stubs/UniqueRefungible.rawdiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueRefungible.raw
@@ -0,0 +1 @@
+TODO
\ No newline at end of file
tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -9,22 +9,35 @@
}
interface ContractHelpers is Dummy {
- function contractOwner(address contr) external view returns (address);
+ function contractOwner(address contractAddress)
+ external
+ view
+ returns (address);
- function sponsoringEnabled(address contr) external view returns (bool);
+ function sponsoringEnabled(address contractAddress)
+ external
+ view
+ returns (bool);
- function toggleSponsoring(address contr, bool enabled) external;
+ function toggleSponsoring(address contractAddress, bool enabled) external;
- function setSponsoringRateLimit(address contr, uint32 rateLimit) external;
+ function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
+ external;
- function allowed(address contr, address user) external view returns (bool);
+ function allowed(address contractAddress, address user)
+ external
+ view
+ returns (bool);
- function allowlistEnabled(address contr) external view returns (bool);
+ function allowlistEnabled(address contractAddress)
+ external
+ view
+ returns (bool);
- function toggleAllowlist(address contr, bool enabled) external;
+ function toggleAllowlist(address contractAddress, bool enabled) external;
function toggleAllowed(
- address contr,
+ address contractAddress,
address user,
bool allowed
) external;