difftreelog
feat calculate signature in compile time
in: master
11 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1096,6 +1096,26 @@
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
+name = "const_format"
+version = "0.2.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "939dc9e2eb9077e0679d2ce32de1ded8531779360b003b4a972a7a39ec263495"
+dependencies = [
+ "const_format_proc_macros",
+]
+
+[[package]]
+name = "const_format_proc_macros"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2353,6 +2373,7 @@
version = "0.1.3"
dependencies = [
"concat-idents",
+ "const_format",
"ethereum",
"evm-coder-procedural",
"evm-core 0.35.0 (git+https://github.com/uniquenetwork/evm?branch=unique-polkadot-v0.9.30)",
@@ -2362,6 +2383,7 @@
"impl-trait-for-tuples",
"pallet-evm 6.0.0-dev (git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit)",
"primitive-types",
+ "sha3-const",
"similar-asserts",
"sp-std 4.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.30)",
]
@@ -11085,6 +11107,12 @@
]
[[package]]
+name = "sha3-const"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af9625d558d174dbdc711248b479271c0fdca39e9d3d67f6e890b3d4251fbf8e"
+
+[[package]]
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
crates/evm-coder/Cargo.tomldiffbeforeafterboth--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -5,6 +5,10 @@
edition = "2021"
[dependencies]
+const_format = { version = "0.2.26", default-features = false }
+sha3-const = { version = "0.1.0", default-features = false }
+# Ethereum uses keccak (=sha3) for selectors
+# sha3 = "0.10.1"
# evm-coder reexports those proc-macro
evm-coder-procedural = { path = "./procedural" }
# Evm uses primitive-types for H160, H256 and others
crates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/solidity_interface.rs
+++ b/crates/evm-coder/procedural/src/solidity_interface.rs
@@ -20,6 +20,7 @@
// about Procedural Macros in Rust book:
// https://doc.rust-lang.org/reference/procedural-macros.html
+use proc_macro2::{TokenStream, Group};
use quote::{quote, ToTokens};
use inflector::cases;
use std::fmt::Write;
@@ -328,6 +329,7 @@
}
}
+#[derive(Debug)]
enum AbiType {
// type
Plain(Ident),
@@ -473,6 +475,7 @@
}
}
+#[derive(Debug)]
struct MethodArg {
name: Ident,
camel_name: String,
@@ -722,13 +725,25 @@
}
}
+ fn expand_selector(&self) -> proc_macro2::TokenStream {
+ let custom_signature = self.expand_custom_signature();
+ quote! {
+ {
+ let a = ::evm_coder::sha3_const::Keccak256::new()
+ .update(#custom_signature.as_bytes())
+ .finalize();
+ [a[0], a[1], a[2], a[3]]
+ }
+ }
+ }
+
fn expand_const(&self) -> proc_macro2::TokenStream {
let screaming_name = &self.screaming_name;
- let selector = u32::to_be_bytes(self.selector);
let selector_str = &self.selector_str;
+ let selector = &self.expand_selector();
quote! {
#[doc = #selector_str]
- const #screaming_name: ::evm_coder::types::bytes4 = [#(#selector,)*];
+ const #screaming_name: ::evm_coder::types::bytes4 = #selector;
}
}
@@ -831,6 +846,59 @@
}
}
+ fn expand_custom_signature(&self) -> proc_macro2::TokenStream {
+ let mut first_comma = true;
+ let mut custom_signature = TokenStream::new();
+ let mut template = self.camel_name.clone() + "(";
+ self.args
+ .iter()
+ .filter_map(|a| {
+ if a.is_special() {
+ return None;
+ };
+
+ match a.ty {
+ AbiType::Plain(ref ident) => Some(ident),
+ _ => None,
+ }
+ })
+ .for_each(|ident| {
+ if !first_comma {
+ custom_signature.extend(quote!(,));
+ template.push(',');
+ } else {
+ first_comma = false;
+ };
+ template.push_str("{}");
+ let ident_str = ident.to_string();
+ match ident_str.as_str() {
+ "address" | "uint8" | "uint16" | "uint32" | "uint64" | "uint128"
+ | "uint256" | "bytes4" | "topic" | "string" | "bytes" | "void" | "caller"
+ | "bool" | "" => {
+ custom_signature.extend(quote!(#ident_str));
+ }
+ _ => {
+ custom_signature.extend(quote! {
+ #ident::SIGNATURE_STRING
+ });
+ }
+ }
+ });
+
+ template.push(')');
+ let mut template = quote!(#template);
+ template.extend(quote!(,));
+ template.extend(custom_signature);
+ let custom_signature_group = Group::new(proc_macro2::Delimiter::Parenthesis, template);
+ let mut custom_signature = quote! {
+ ::evm_coder::const_format::formatcp!
+ };
+ custom_signature.extend(custom_signature_group.to_token_stream());
+
+ // println!("!!!!! {}", custom_signature);
+ custom_signature
+ }
+
fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
let camel_name = &self.camel_name;
let mutability = match self.mutability {
@@ -847,15 +915,17 @@
.map(MethodArg::expand_solidity_argument);
let docs = &self.docs;
let selector_str = &self.selector_str;
- let selector = self.selector;
+ let selector = &self.expand_selector();
let hide = self.hide;
+ let custom_signature = self.expand_custom_signature();
let is_payable = self.has_value_args;
quote! {
SolidityFunction {
docs: &[#(#docs),*],
selector_str: #selector_str,
- selector: #selector,
hide: #hide,
+ selector: u32::from_be_bytes(#selector),
+ custom_signature: #custom_signature,
name: #camel_name,
mutability: #mutability,
is_payable: #is_payable,
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -90,6 +90,8 @@
pub use evm_coder_procedural::solidity;
/// See [`solidity_interface`]
pub use evm_coder_procedural::weight;
+pub use const_format;
+pub use sha3_const;
/// Derives [`ToLog`] for enum
///
@@ -227,6 +229,14 @@
}
}
+ impl SignatureString for EthCrossAccount {
+ const SIGNATURE_STRING: &'static str = "(address,uint256)";
+ }
+
+ pub trait SignatureString {
+ const SIGNATURE_STRING: &'static str;
+ }
+
/// Convert `CrossAccountId` to `uint256`.
pub fn convert_cross_account_to_uint256<T: pallet_evm::account::Config>(
from: &T::CrossAccountId,
@@ -348,6 +358,18 @@
assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);
}
+ // #[test]
+ // fn function_selector_generation_1() {
+ // assert_eq!(
+ // fn_selector!(transferFromCrossAccountToCrossAccount(
+ // EthCrossAccount,
+ // EthCrossAccount,
+ // uint256
+ // )),
+ // 2543295963
+ // );
+ // }
+
#[test]
fn event_topic_generation() {
assert_eq!(
crates/evm-coder/src/solidity.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -35,6 +35,12 @@
use crate::types::*;
#[derive(Default)]
+pub struct FunctionSelectorMaker {
+ pub name: string,
+ pub args: Vec<fn() -> string>,
+}
+
+#[derive(Default)]
pub struct TypeCollector {
/// Code => id
/// id ordering is required to perform topo-sort on the resulting data
@@ -482,11 +488,25 @@
View,
Mutable,
}
+
+// fn fn_selector_str(input: &str) -> u32 {
+// use sha3::Digest;
+// let mut hasher = sha3::Keccak256::new();
+// hasher.update(input.as_bytes());
+// let result = hasher.finalize();
+
+// let mut selector_bytes = [0; 4];
+// selector_bytes.copy_from_slice(&result[0..4]);
+
+// u32::from_be_bytes(selector_bytes)
+// }
+
pub struct SolidityFunction<A, R> {
pub docs: &'static [&'static str],
pub selector_str: &'static str,
pub selector: u32,
pub hide: bool,
+ pub custom_signature: &'static str,
pub name: &'static str,
pub args: A,
pub result: R,
@@ -512,7 +532,7 @@
writeln!(
writer,
"\t{hide_comment}/// or in textual repr: {}",
- self.selector_str
+ self.custom_signature
)?;
write!(writer, "\t{hide_comment}function {}(", self.name)?;
self.args.solidity_name(writer, tc)?;
pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-contract-helpers/Cargo.toml
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -27,7 +27,7 @@
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-common = { default-features = false, path = '../../pallets/common' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
-pallet-evm-transaction-payment = { default-features = false, path = '../../pallets/evm-transaction-payment' }
+pallet-evm-transaction-payment = { default-features = false, path = '../../pallets/evm-transaction-payment' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs', features = [
'serde1',
] }
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of magic contract1819use core::marker::PhantomData;20use evm_coder::{21 abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,22};23use pallet_evm::{24 ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,25 account::CrossAccountId,26};27use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};28use pallet_evm_transaction_payment::CallContext;29use sp_core::{H160, U256};30use up_data_structs::SponsorshipState;31use crate::{32 AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringFeeLimit,33 SponsoringRateLimit, SponsoringModeT, Sponsoring,34};35use frame_support::traits::Get;36use up_sponsorship::SponsorshipHandler;37use sp_std::vec::Vec;3839/// Pallet events.40#[derive(ToLog)]41pub enum ContractHelpersEvents {42 /// Contract sponsor was set.43 ContractSponsorSet {44 /// Contract address of the affected collection.45 #[indexed]46 contract_address: address,47 /// New sponsor address.48 sponsor: address,49 },5051 /// New sponsor was confirm.52 ContractSponsorshipConfirmed {53 /// Contract address of the affected collection.54 #[indexed]55 contract_address: address,56 /// New sponsor address.57 sponsor: address,58 },5960 /// Collection sponsor was removed.61 ContractSponsorRemoved {62 /// Contract address of the affected collection.63 #[indexed]64 contract_address: address,65 },66}6768/// See [`ContractHelpersCall`]69pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);70impl<T: Config> WithRecorder<T> for ContractHelpers<T> {71 fn recorder(&self) -> &SubstrateRecorder<T> {72 &self.073 }7475 fn into_recorder(self) -> SubstrateRecorder<T> {76 self.077 }78}7980/// @title Magic contract, which allows users to reconfigure other contracts81#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents))]82impl<T: Config> ContractHelpers<T>83where84 T::AccountId: AsRef<[u8; 32]>,85{86 /// Get user, which deployed specified contract87 /// @dev May return zero address in case if contract is deployed88 /// using uniquenetwork evm-migration pallet, or using other terms not89 /// intended by pallet-evm90 /// @dev Returns zero address if contract does not exists91 /// @param contractAddress Contract to get owner of92 /// @return address Owner of contract93 fn contract_owner(&self, contract_address: address) -> Result<address> {94 Ok(<Owner<T>>::get(contract_address))95 }9697 /// Set sponsor.98 /// @param contractAddress Contract for which a sponsor is being established.99 /// @param sponsor User address who set as pending sponsor.100 fn set_sponsor(101 &mut self,102 caller: caller,103 contract_address: address,104 sponsor: address,105 ) -> Result<void> {106 self.recorder().consume_sload()?;107 self.recorder().consume_sstore()?;108109 Pallet::<T>::set_sponsor(110 &T::CrossAccountId::from_eth(caller),111 contract_address,112 &T::CrossAccountId::from_eth(sponsor),113 )114 .map_err(dispatch_to_evm::<T>)?;115116 Ok(())117 }118119 /// Set contract as self sponsored.120 ///121 /// @param contractAddress Contract for which a self sponsoring is being enabled.122 fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {123 self.recorder().consume_sload()?;124 self.recorder().consume_sstore()?;125126 let caller = T::CrossAccountId::from_eth(caller);127128 Pallet::<T>::ensure_owner(contract_address, *caller.as_eth())129 .map_err(dispatch_to_evm::<T>)?;130131 Pallet::<T>::force_set_sponsor(132 contract_address,133 &T::CrossAccountId::from_eth(contract_address),134 )135 .map_err(dispatch_to_evm::<T>)?;136137 Ok(())138 }139140 /// Remove sponsor.141 ///142 /// @param contractAddress Contract for which a sponsorship is being removed.143 fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {144 self.recorder().consume_sload()?;145 self.recorder().consume_sstore()?;146147 Pallet::<T>::remove_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)148 .map_err(dispatch_to_evm::<T>)?;149150 Ok(())151 }152153 /// Confirm sponsorship.154 ///155 /// @dev Caller must be same that set via [`setSponsor`].156 ///157 /// @param contractAddress Сontract for which need to confirm sponsorship.158 fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {159 self.recorder().consume_sload()?;160 self.recorder().consume_sstore()?;161162 Pallet::<T>::confirm_sponsorship(&T::CrossAccountId::from_eth(caller), contract_address)163 .map_err(dispatch_to_evm::<T>)?;164165 Ok(())166 }167168 /// Get current sponsor.169 ///170 /// @param contractAddress The contract for which a sponsor is requested.171 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.172 fn sponsor(&self, contract_address: address) -> Result<(address, uint256)> {173 let sponsor =174 Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;175 Ok(pallet_common::eth::convert_cross_account_to_tuple::<T>(176 &sponsor,177 ))178 }179180 /// Check tat contract has confirmed sponsor.181 ///182 /// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.183 /// @return **true** if contract has confirmed sponsor.184 fn has_sponsor(&self, contract_address: address) -> Result<bool> {185 Ok(Pallet::<T>::get_sponsor(contract_address).is_some())186 }187188 /// Check tat contract has pending sponsor.189 ///190 /// @param contractAddress The contract for which the presence of a pending sponsor is checked.191 /// @return **true** if contract has pending sponsor.192 fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {193 Ok(match Sponsoring::<T>::get(contract_address) {194 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false,195 SponsorshipState::Unconfirmed(_) => true,196 })197 }198199 fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {200 Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)201 }202203 fn set_sponsoring_mode(204 &mut self,205 caller: caller,206 contract_address: address,207 // TODO: implement support for enums in evm-coder208 mode: uint8,209 ) -> Result<void> {210 self.recorder().consume_sload()?;211 self.recorder().consume_sstore()?;212213 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;214 let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;215 <Pallet<T>>::set_sponsoring_mode(contract_address, mode);216217 Ok(())218 }219220 /// Get current contract sponsoring rate limit221 /// @param contractAddress Contract to get sponsoring rate limit of222 /// @return uint32 Amount of blocks between two sponsored transactions223 fn sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {224 self.recorder().consume_sload()?;225226 Ok(<SponsoringRateLimit<T>>::get(contract_address)227 .try_into()228 .map_err(|_| "rate limit > u32::MAX")?)229 }230231 /// Set contract sponsoring rate limit232 /// @dev Sponsoring rate limit - is a minimum amount of blocks that should233 /// pass between two sponsored transactions234 /// @param contractAddress Contract to change sponsoring rate limit of235 /// @param rateLimit Target rate limit236 /// @dev Only contract owner can change this setting237 fn set_sponsoring_rate_limit(238 &mut self,239 caller: caller,240 contract_address: address,241 rate_limit: uint32,242 ) -> Result<void> {243 self.recorder().consume_sload()?;244 self.recorder().consume_sstore()?;245246 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;247 <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());248 Ok(())249 }250251 /// Set contract sponsoring fee limit252 /// @dev Sponsoring fee limit - is maximum fee that could be spent by253 /// single transaction254 /// @param contractAddress Contract to change sponsoring fee limit of255 /// @param feeLimit Fee limit256 /// @dev Only contract owner can change this setting257 fn set_sponsoring_fee_limit(258 &mut self,259 caller: caller,260 contract_address: address,261 fee_limit: uint256,262 ) -> Result<void> {263 self.recorder().consume_sload()?;264 self.recorder().consume_sstore()?;265266 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;267 <Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit.into())268 .map_err(dispatch_to_evm::<T>)?;269 Ok(())270 }271272 /// Get current contract sponsoring fee limit273 /// @param contractAddress Contract to get sponsoring fee limit of274 /// @return uint256 Maximum amount of fee that could be spent by single275 /// transaction276 fn sponsoring_fee_limit(&self, contract_address: address) -> Result<uint256> {277 self.recorder().consume_sload()?;278279 Ok(get_sponsoring_fee_limit::<T>(contract_address))280 }281282 /// Is specified user present in contract allow list283 /// @dev Contract owner always implicitly included284 /// @param contractAddress Contract to check allowlist of285 /// @param user User to check286 /// @return bool Is specified users exists in contract allowlist287 fn allowed(&self, contract_address: address, user: address) -> Result<bool> {288 self.0.consume_sload()?;289 Ok(<Pallet<T>>::allowed(contract_address, user))290 }291292 /// Toggle user presence in contract allowlist293 /// @param contractAddress Contract to change allowlist of294 /// @param user Which user presence should be toggled295 /// @param isAllowed `true` if user should be allowed to be sponsored296 /// or call this contract, `false` otherwise297 /// @dev Only contract owner can change this setting298 fn toggle_allowed(299 &mut self,300 caller: caller,301 contract_address: address,302 user: address,303 is_allowed: bool,304 ) -> Result<void> {305 self.recorder().consume_sload()?;306 self.recorder().consume_sstore()?;307308 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;309 <Pallet<T>>::toggle_allowed(contract_address, user, is_allowed);310311 Ok(())312 }313314 /// Is this contract has allowlist access enabled315 /// @dev Allowlist always can have users, and it is used for two purposes:316 /// in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist317 /// in case of allowlist access enabled, only users from allowlist may call this contract318 /// @param contractAddress Contract to get allowlist access of319 /// @return bool Is specified contract has allowlist access enabled320 fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {321 Ok(<AllowlistEnabled<T>>::get(contract_address))322 }323324 /// Toggle contract allowlist access325 /// @param contractAddress Contract to change allowlist access of326 /// @param enabled Should allowlist access to be enabled?327 fn toggle_allowlist(328 &mut self,329 caller: caller,330 contract_address: address,331 enabled: bool,332 ) -> Result<void> {333 self.recorder().consume_sload()?;334 self.recorder().consume_sstore()?;335336 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;337 <Pallet<T>>::toggle_allowlist(contract_address, enabled);338 Ok(())339 }340}341342/// Implements [`OnMethodCall`], which delegates call to [`ContractHelpers`]343pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);344impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T>345where346 T::AccountId: AsRef<[u8; 32]>,347{348 fn is_reserved(contract: &sp_core::H160) -> bool {349 contract == &T::ContractAddress::get()350 }351352 fn is_used(contract: &sp_core::H160) -> bool {353 contract == &T::ContractAddress::get()354 }355356 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {357 // TODO: Extract to another OnMethodCall handler358 if <AllowlistEnabled<T>>::get(handle.code_address())359 && !<Pallet<T>>::allowed(handle.code_address(), handle.context().caller)360 {361 return Some(Err(PrecompileFailure::Revert {362 exit_status: ExitRevert::Reverted,363 output: {364 let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));365 writer.string("Target contract is allowlisted");366 writer.finish()367 },368 }));369 }370371 if handle.code_address() != T::ContractAddress::get() {372 return None;373 }374375 let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));376 pallet_evm_coder_substrate::call(handle, helpers)377 }378379 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {380 (contract == &T::ContractAddress::get())381 .then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())382 }383}384385/// Hooks into contract creation, storing owner of newly deployed contract386pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);387impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {388 fn on_create(owner: H160, contract: H160) {389 <Owner<T>>::insert(contract, owner);390 }391}392393/// Bridge to pallet-sponsoring394pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);395impl<T: Config> SponsorshipHandler<T::CrossAccountId, CallContext>396 for HelpersContractSponsoring<T>397{398 fn get_sponsor(399 who: &T::CrossAccountId,400 call_context: &CallContext,401 ) -> Option<T::CrossAccountId> {402 let contract_address = call_context.contract_address;403 let mode = <Pallet<T>>::sponsoring_mode(contract_address);404 if mode == SponsoringModeT::Disabled {405 return None;406 }407408 let sponsor = match <Pallet<T>>::get_sponsor(contract_address) {409 Some(sponsor) => sponsor,410 None => return None,411 };412413 if mode == SponsoringModeT::Allowlisted414 && !<Pallet<T>>::allowed(contract_address, *who.as_eth())415 {416 return None;417 }418 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;419420 if let Some(last_tx_block) = <SponsorBasket<T>>::get(contract_address, who.as_eth()) {421 let limit = <SponsoringRateLimit<T>>::get(contract_address);422423 let timeout = last_tx_block + limit;424 if block_number < timeout {425 return None;426 }427 }428429 let sponsored_fee_limit = get_sponsoring_fee_limit::<T>(contract_address);430431 if call_context.max_fee > sponsored_fee_limit {432 return None;433 }434435 <SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);436437 Some(sponsor)438 }439}440441fn get_sponsoring_fee_limit<T: Config>(contract_address: address) -> uint256 {442 <SponsoringFeeLimit<T>>::get(contract_address)443 .get(&0xffffffff)444 .cloned()445 .unwrap_or(U256::MAX)446}447448generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);449generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -16,6 +16,8 @@
//! ERC-20 standart support implementation.
+extern crate alloc;
+use alloc::{format, string::ToString};
use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
use core::convert::TryInto;
use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -20,6 +20,7 @@
//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
extern crate alloc;
+use alloc::{format, string::ToString};
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,
pallets/refungible/Cargo.tomldiffbeforeafterboth--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -26,7 +26,9 @@
struct-versioning = { path = "../../crates/struct-versioning" }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
ethereum = { version = "0.12.0", default-features = false }
-scale-info = { version = "2.0.1", default-features = false, features = ["derive",] }
+scale-info = { version = "2.0.1", default-features = false, features = [
+ "derive",
+] }
derivative = { version = "2.2.0", features = ["use_core"] }
[features]
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -21,6 +21,7 @@
extern crate alloc;
+use alloc::{format, string::ToString};
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,