git.delta.rocks / unique-network / refs/commits / 4efa9ce62081

difftreelog

doc(pallet-evm-contract-helpers): document public api

Yaroslav Bolyukin2022-07-12parent: #c098935.patch.diff
in: master

7 files changed

addedpallets/evm-contract-helpers/README.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-contract-helpers/README.md
@@ -0,0 +1,13 @@
+# EVM Contract Helpers
+
+This pallet extends pallet-evm contracts with several new functions.
+
+## Overview
+
+Evm contract helpers pallet provides ability to
+
+- Tracking and getting of user, which deployed contract
+- Sponsoring EVM contract calls (Make transaction calls to be free for users, instead making them being paid from contract address)
+- Allowlist access mode
+
+As most of those functions are intented to be consumed by ethereum users, only API provided by this pallet is [ContractHelpers magic contract](./src/stubs/ContractHelpers.sol)
\ No newline at end of file
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
before · pallets/evm-contract-helpers/src/eth.rs
1// 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/>.1617use core::marker::PhantomData;18use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};19use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};20use pallet_evm::{21	ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,22	account::CrossAccountId,23};24use sp_core::H160;25use up_data_structs::SponsorshipState;26use crate::{27	AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,28	Sponsoring,29};30use frame_support::traits::Get;31use up_sponsorship::SponsorshipHandler;32use sp_std::vec::Vec;3334struct ContractHelpers<T: Config>(SubstrateRecorder<T>);35impl<T: Config> WithRecorder<T> for ContractHelpers<T> {36	fn recorder(&self) -> &SubstrateRecorder<T> {37		&self.038	}3940	fn into_recorder(self) -> SubstrateRecorder<T> {41		self.042	}43}4445#[solidity_interface(name = ContractHelpers)]46impl<T: Config> ContractHelpers<T>47where48	T::AccountId: AsRef<[u8; 32]>,49{50	/// Get contract ovner51	///52	/// @param contractAddress contract for which the owner is being determined.53	/// @return Contract owner.54	fn contract_owner(&self, contract_address: address) -> Result<address> {55		Ok(<Owner<T>>::get(contract_address))56	}5758	/// Set sponsor.59	///60	/// @param contractAddress Contract for which a sponsor is being established.61	/// @param sponsor User address who set as pending sponsor.62	fn set_sponsor(63		&mut self,64		caller: caller,65		contract_address: address,66		sponsor: address,67	) -> Result<void> {68		self.recorder().consume_sload()?;69		self.recorder().consume_sstore()?;7071		Pallet::<T>::set_sponsor(72			&T::CrossAccountId::from_eth(caller),73			contract_address,74			&T::CrossAccountId::from_eth(sponsor),75		)76		.map_err(dispatch_to_evm::<T>)?;7778		Ok(())79	}8081	/// Set contract as self sponsored.82	///83	/// @param contractAddress Contract for which a self sponsoring is being enabled.84	fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {85		self.recorder().consume_sload()?;86		self.recorder().consume_sstore()?;8788		Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)89			.map_err(dispatch_to_evm::<T>)?;9091		Ok(())92	}9394	/// Remove sponsor.95	///96	/// @param contractAddress Contract for which a sponsorship is being removed.97	fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {98		self.recorder().consume_sload()?;99		self.recorder().consume_sstore()?;100101		Pallet::<T>::remove_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)102			.map_err(dispatch_to_evm::<T>)?;103104		Ok(())105	}106107	/// Confirm sponsorship.108	///109	/// @dev Caller must be same that set via [`setSponsor`].110	///111	/// @param contractAddress Сontract for which need to confirm sponsorship.112	fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {113		self.recorder().consume_sload()?;114		self.recorder().consume_sstore()?;115116		Pallet::<T>::confirm_sponsorship(&T::CrossAccountId::from_eth(caller), contract_address)117			.map_err(dispatch_to_evm::<T>)?;118119		Ok(())120	}121122	/// Get current sponsor.123	///124	/// @param contractAddress The contract for which a sponsor is requested.125	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.126	fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {127		let sponsor =128			Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;129		let result: (address, uint256) = if sponsor.is_canonical_substrate() {130			let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);131			(Default::default(), sponsor)132		} else {133			let sponsor = *sponsor.as_eth();134			(sponsor, Default::default())135		};136		Ok(result)137	}138139	/// Check tat contract has confirmed sponsor.140	///141	/// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.142	/// @return **true** if contract has confirmed sponsor.143	fn has_sponsor(&self, contract_address: address) -> Result<bool> {144		Ok(Pallet::<T>::get_sponsor(contract_address).is_some())145	}146147	/// Check tat contract has pending sponsor.148	///149	/// @param contractAddress The contract for which the presence of a pending sponsor is checked.150	/// @return **true** if contract has pending sponsor.151	fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {152		Ok(match Sponsoring::<T>::get(contract_address) {153			SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false,154			SponsorshipState::Unconfirmed(_) => true,155		})156	}157158	fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {159		Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)160	}161162	fn set_sponsoring_mode(163		&mut self,164		caller: caller,165		contract_address: address,166		mode: uint8,167	) -> Result<void> {168		self.recorder().consume_sload()?;169		self.recorder().consume_sstore()?;170171		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;172		let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;173		<Pallet<T>>::set_sponsoring_mode(contract_address, mode);174175		Ok(())176	}177178	fn sponsoring_mode(&self, contract_address: address) -> Result<uint8> {179		Ok(<Pallet<T>>::sponsoring_mode(contract_address).to_eth())180	}181182	fn set_sponsoring_rate_limit(183		&mut self,184		caller: caller,185		contract_address: address,186		rate_limit: uint32,187	) -> Result<void> {188		self.recorder().consume_sload()?;189		self.recorder().consume_sstore()?;190191		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;192		<Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());193194		Ok(())195	}196197	fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {198		Ok(<SponsoringRateLimit<T>>::get(contract_address)199			.try_into()200			.map_err(|_| "rate limit > u32::MAX")?)201	}202203	fn allowed(&self, contract_address: address, user: address) -> Result<bool> {204		self.0.consume_sload()?;205		Ok(<Pallet<T>>::allowed(contract_address, user))206	}207208	fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {209		Ok(<AllowlistEnabled<T>>::get(contract_address))210	}211212	fn toggle_allowlist(213		&mut self,214		caller: caller,215		contract_address: address,216		enabled: bool,217	) -> Result<void> {218		self.recorder().consume_sload()?;219		self.recorder().consume_sstore()?;220221		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;222		<Pallet<T>>::toggle_allowlist(contract_address, enabled);223224		Ok(())225	}226227	fn toggle_allowed(228		&mut self,229		caller: caller,230		contract_address: address,231		user: address,232		is_allowed: bool,233	) -> Result<void> {234		self.recorder().consume_sload()?;235		self.recorder().consume_sstore()?;236237		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;238		<Pallet<T>>::toggle_allowed(contract_address, user, is_allowed);239240		Ok(())241	}242}243244pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);245impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T>246where247	T::AccountId: AsRef<[u8; 32]>,248{249	fn is_reserved(contract: &sp_core::H160) -> bool {250		contract == &T::ContractAddress::get()251	}252253	fn is_used(contract: &sp_core::H160) -> bool {254		contract == &T::ContractAddress::get()255	}256257	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {258		// TODO: Extract to another OnMethodCall handler259		if <AllowlistEnabled<T>>::get(handle.code_address())260			&& !<Pallet<T>>::allowed(handle.code_address(), handle.context().caller)261		{262			return Some(Err(PrecompileFailure::Revert {263				exit_status: ExitRevert::Reverted,264				output: {265					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));266					writer.string("Target contract is allowlisted");267					writer.finish()268				},269			}));270		}271272		if handle.code_address() != T::ContractAddress::get() {273			return None;274		}275276		let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));277		pallet_evm_coder_substrate::call(handle, helpers)278	}279280	fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {281		(contract == &T::ContractAddress::get())282			.then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())283	}284}285286pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);287impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {288	fn on_create(owner: H160, contract: H160) {289		<Owner<T>>::insert(contract, owner);290	}291}292293pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);294impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>295	for HelpersContractSponsoring<T>296{297	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {298		let (contract_address, _) = call;299		let mode = <Pallet<T>>::sponsoring_mode(*contract_address);300		if mode == SponsoringModeT::Disabled {301			return None;302		}303304		let sponsor = match <Pallet<T>>::get_sponsor(*contract_address) {305			Some(sponsor) => sponsor,306			None => return None,307		};308309		if mode == SponsoringModeT::Allowlisted310			&& !<Pallet<T>>::allowed(*contract_address, *who.as_eth())311		{312			return None;313		}314		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;315316		if let Some(last_tx_block) = <SponsorBasket<T>>::get(contract_address, who.as_eth()) {317			let limit = <SponsoringRateLimit<T>>::get(contract_address);318319			let timeout = last_tx_block + limit;320			if block_number < timeout {321				return None;322			}323		}324325		<SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);326327		Some(sponsor)328	}329}330331generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);332generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);
after · pallets/evm-contract-helpers/src/eth.rs
1// 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::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};21use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};22use pallet_evm::{23	ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,24	account::CrossAccountId,25};26use sp_core::H160;27use up_data_structs::SponsorshipState;28use crate::{29	AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,30	Sponsoring,31};32use frame_support::traits::Get;33use up_sponsorship::SponsorshipHandler;34use sp_std::vec::Vec;3536/// See [`ContractHelpersCall`]37pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);38impl<T: Config> WithRecorder<T> for ContractHelpers<T> {39	fn recorder(&self) -> &SubstrateRecorder<T> {40		&self.041	}4243	fn into_recorder(self) -> SubstrateRecorder<T> {44		self.045	}46}4748/// @title Magic contract, which allows users to reconfigure other contracts49#[solidity_interface(name = ContractHelpers)]50impl<T: Config> ContractHelpers<T>51where52	T::AccountId: AsRef<[u8; 32]>,53{54	/// Get user, which deployed specified contract55	/// @dev May return zero address in case if contract is deployed56	///  using uniquenetwork evm-migration pallet, or using other terms not57	///  intended by pallet-evm58	/// @dev Returns zero address if contract does not exists59	/// @param contractAddress Contract to get owner of60	/// @return address Owner of contract61	fn contract_owner(&self, contract_address: address) -> Result<address> {62		Ok(<Owner<T>>::get(contract_address))63	}6465	/// Set sponsor.66	/// @param contractAddress Contract for which a sponsor is being established.67	/// @param sponsor User address who set as pending sponsor.68	fn set_sponsor(69		&mut self,70		caller: caller,71		contract_address: address,72		sponsor: address,73	) -> Result<void> {74		self.recorder().consume_sload()?;75		self.recorder().consume_sstore()?;7677		Pallet::<T>::set_sponsor(78			&T::CrossAccountId::from_eth(caller),79			contract_address,80			&T::CrossAccountId::from_eth(sponsor),81		)82		.map_err(dispatch_to_evm::<T>)?;8384		Ok(())85	}8687	/// Set contract as self sponsored.88	///89	/// @param contractAddress Contract for which a self sponsoring is being enabled.90	fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {91		self.recorder().consume_sload()?;92		self.recorder().consume_sstore()?;9394		Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)95			.map_err(dispatch_to_evm::<T>)?;9697		Ok(())98	}99100	/// Remove sponsor.101	///102	/// @param contractAddress Contract for which a sponsorship is being removed.103	fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {104		self.recorder().consume_sload()?;105		self.recorder().consume_sstore()?;106107		Pallet::<T>::remove_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)108			.map_err(dispatch_to_evm::<T>)?;109110		Ok(())111	}112113	/// Confirm sponsorship.114	///115	/// @dev Caller must be same that set via [`setSponsor`].116	///117	/// @param contractAddress Сontract for which need to confirm sponsorship.118	fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {119		self.recorder().consume_sload()?;120		self.recorder().consume_sstore()?;121122		Pallet::<T>::confirm_sponsorship(&T::CrossAccountId::from_eth(caller), contract_address)123			.map_err(dispatch_to_evm::<T>)?;124125		Ok(())126	}127128	/// Get current sponsor.129	///130	/// @param contractAddress The contract for which a sponsor is requested.131	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.132	fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {133		let sponsor =134			Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;135		let result: (address, uint256) = if sponsor.is_canonical_substrate() {136			let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);137			(Default::default(), sponsor)138		} else {139			let sponsor = *sponsor.as_eth();140			(sponsor, Default::default())141		};142		Ok(result)143	}144145	/// Check tat contract has confirmed sponsor.146	///147	/// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.148	/// @return **true** if contract has confirmed sponsor.149	fn has_sponsor(&self, contract_address: address) -> Result<bool> {150		Ok(Pallet::<T>::get_sponsor(contract_address).is_some())151	}152153	/// Check tat contract has pending sponsor.154	///155	/// @param contractAddress The contract for which the presence of a pending sponsor is checked.156	/// @return **true** if contract has pending sponsor.157	fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {158		Ok(match Sponsoring::<T>::get(contract_address) {159			SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false,160			SponsorshipState::Unconfirmed(_) => true,161		})162	}163164	fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {165		Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)166	}167168	fn set_sponsoring_mode(169		&mut self,170		caller: caller,171		contract_address: address,172		// TODO: implement support for enums in evm-coder173		mode: uint8,174	) -> Result<void> {175		self.recorder().consume_sload()?;176		self.recorder().consume_sstore()?;177178		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;179		let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;180		<Pallet<T>>::set_sponsoring_mode(contract_address, mode);181182		Ok(())183	}184185	/// Get current contract sponsoring rate limit186	/// @param contractAddress Contract to get sponsoring mode of187	/// @return uint32 Amount of blocks between two sponsored transactions188	fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {189		Ok(<SponsoringRateLimit<T>>::get(contract_address)190			.try_into()191			.map_err(|_| "rate limit > u32::MAX")?)192	}193194	/// Set contract sponsoring rate limit195	/// @dev Sponsoring rate limit - is a minimum amount of blocks that should196	///  pass between two sponsored transactions197	/// @param contractAddress Contract to change sponsoring rate limit of198	/// @param rateLimit Target rate limit199	/// @dev Only contract owner can change this setting200	fn set_sponsoring_rate_limit(201		&mut self,202		caller: caller,203		contract_address: address,204		rate_limit: uint32,205	) -> Result<void> {206		self.recorder().consume_sload()?;207		self.recorder().consume_sstore()?;208209		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;210		<Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());211		Ok(())212	}213214	/// Is specified user present in contract allow list215	/// @dev Contract owner always implicitly included216	/// @param contractAddress Contract to check allowlist of217	/// @param user User to check218	/// @return bool Is specified users exists in contract allowlist219	fn allowed(&self, contract_address: address, user: address) -> Result<bool> {220		self.0.consume_sload()?;221		Ok(<Pallet<T>>::allowed(contract_address, user))222	}223224	/// Toggle user presence in contract allowlist225	/// @param contractAddress Contract to change allowlist of226	/// @param user Which user presence should be toggled227	/// @param isAllowed `true` if user should be allowed to be sponsored228	///  or call this contract, `false` otherwise229	/// @dev Only contract owner can change this setting230	fn toggle_allowed(231		&mut self,232		caller: caller,233		contract_address: address,234		user: address,235		is_allowed: bool,236	) -> Result<void> {237		self.recorder().consume_sload()?;238		self.recorder().consume_sstore()?;239240		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;241		<Pallet<T>>::toggle_allowed(contract_address, user, is_allowed);242243		Ok(())244	}245246	/// Is this contract has allowlist access enabled247	/// @dev Allowlist always can have users, and it is used for two purposes:248	///  in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist249	///  in case of allowlist access enabled, only users from allowlist may call this contract250	/// @param contractAddress Contract to get allowlist access of251	/// @return bool Is specified contract has allowlist access enabled252	fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {253		Ok(<AllowlistEnabled<T>>::get(contract_address))254	}255256	/// Toggle contract allowlist access257	/// @param contractAddress Contract to change allowlist access of258	/// @param enabled Should allowlist access to be enabled?259	fn toggle_allowlist(260		&mut self,261		caller: caller,262		contract_address: address,263		enabled: bool,264	) -> Result<void> {265		self.recorder().consume_sload()?;266		self.recorder().consume_sstore()?;267268		<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;269		<Pallet<T>>::toggle_allowlist(contract_address, enabled);270		Ok(())271	}272}273274/// Implements [`OnMethodCall`], which delegates call to [`ContractHelpers`]275pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);276impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T>277where278	T::AccountId: AsRef<[u8; 32]>,279{280	fn is_reserved(contract: &sp_core::H160) -> bool {281		contract == &T::ContractAddress::get()282	}283284	fn is_used(contract: &sp_core::H160) -> bool {285		contract == &T::ContractAddress::get()286	}287288	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {289		// TODO: Extract to another OnMethodCall handler290		if <AllowlistEnabled<T>>::get(handle.code_address())291			&& !<Pallet<T>>::allowed(handle.code_address(), handle.context().caller)292		{293			return Some(Err(PrecompileFailure::Revert {294				exit_status: ExitRevert::Reverted,295				output: {296					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));297					writer.string("Target contract is allowlisted");298					writer.finish()299				},300			}));301		}302303		if handle.code_address() != T::ContractAddress::get() {304			return None;305		}306307		let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));308		pallet_evm_coder_substrate::call(handle, helpers)309	}310311	fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {312		(contract == &T::ContractAddress::get())313			.then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())314	}315}316317/// Hooks into contract creation, storing owner of newly deployed contract318pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);319impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {320	fn on_create(owner: H160, contract: H160) {321		<Owner<T>>::insert(contract, owner);322	}323}324325/// Bridge to pallet-sponsoring326pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);327impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>328	for HelpersContractSponsoring<T>329{330	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {331		let (contract_address, _) = call;332		let mode = <Pallet<T>>::sponsoring_mode(*contract_address);333		if mode == SponsoringModeT::Disabled {334			return None;335		}336337		let sponsor = match <Pallet<T>>::get_sponsor(*contract_address) {338			Some(sponsor) => sponsor,339			None => return None,340		};341342		if mode == SponsoringModeT::Allowlisted343			&& !<Pallet<T>>::allowed(*contract_address, *who.as_eth())344		{345			return None;346		}347		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;348349		if let Some(last_tx_block) = <SponsorBasket<T>>::get(contract_address, who.as_eth()) {350			let limit = <SponsoringRateLimit<T>>::get(contract_address);351352			let timeout = last_tx_block + limit;353			if block_number < timeout {354				return None;355			}356		}357358		<SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);359360		Some(sponsor)361	}362}363364generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);365generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);
modifiedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -14,7 +14,9 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
+#![doc = include_str!("../README.md")]
 #![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
 
 use codec::{Decode, Encode, MaxEncodedLen};
 pub use pallet::*;
@@ -35,13 +37,16 @@
 	pub trait Config:
 		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config
 	{
+		/// Address, under which magic contract will be available
 		type ContractAddress: Get<H160>;
+		/// In case of enabled sponsoring, but no sponsoring rate limit set,
+		/// this value will be used implicitly
 		type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
-		/// This method is only executable by owner.
+		/// This method is only executable by contract owner
 		NoPermission,
 
 		/// No pending sponsor for contract.
@@ -217,6 +222,7 @@
 			}
 		}
 
+		/// Get current sponsoring mode, performing lazy migration from legacy storage
 		pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {
 			<SponsoringMode<T>>::get(contract)
 				.or_else(|| {
@@ -225,6 +231,7 @@
 				.unwrap_or_default()
 		}
 
+		/// Reconfigure contract sponsoring mode
 		pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {
 			if mode == SponsoringModeT::Disabled {
 				<SponsoringMode<T>>::remove(contract);
@@ -234,22 +241,27 @@
 			<SelfSponsoring<T>>::remove(contract)
 		}
 
+		/// Set duration between two sponsored contract calls
 		pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {
 			<SponsoringRateLimit<T>>::insert(contract, rate_limit);
 		}
 
+		/// Is user added to allowlist, or he is owner of specified contract
 		pub fn allowed(contract: H160, user: H160) -> bool {
 			<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
 		}
 
+		/// Toggle contract allowlist access
 		pub fn toggle_allowlist(contract: H160, enabled: bool) {
 			<AllowlistEnabled<T>>::insert(contract, enabled)
 		}
 
+		/// Toggle user presence in contract's allowlist
 		pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {
 			<Allowlist<T>>::insert(contract, user, allowed);
 		}
 
+		/// Throw error if user is not allowed to reconfigure target contract
 		pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {
 			ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);
 			Ok(())
@@ -257,10 +269,15 @@
 	}
 }
 
-#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen)]
+/// Available contract sponsoring modes
+#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]
 pub enum SponsoringModeT {
+	/// Sponsoring is disabled
+	#[default]
 	Disabled,
+	/// Only users from allowlist will be sponsored
 	Allowlisted,
+	/// All users will be sponsored
 	Generous,
 }
 
@@ -279,11 +296,5 @@
 			SponsoringModeT::Allowlisted => 1,
 			SponsoringModeT::Generous => 2,
 		}
-	}
-}
-
-impl Default for SponsoringModeT {
-	fn default() -> Self {
-		Self::Disabled
 	}
 }
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/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
@@ -3,12 +3,6 @@
 
 pragma solidity >=0.8.0 <0.9.0;
 
-/// @dev anonymous struct
-struct Tuple0 {
-	address field_0;
-	uint256 field_1;
-}
-
 /// @dev common stubs holder
 contract Dummy {
 	uint8 dummy;
@@ -27,14 +21,18 @@
 	}
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x6073d917
+/// @title Magic contract, which allows users to reconfigure other contracts
+/// @dev the ERC-165 identifier for this interface is 0xd77fab70
 contract ContractHelpers is Dummy, ERC165 {
-	/// Get contract ovner
-	///
-	/// @param contractAddress contract for which the owner is being determined.
-	/// @return Contract owner.
-	///
-	/// Selector: contractOwner(address) 5152b14c
+	/// Get user, which deployed specified contract
+	/// @dev May return zero address in case if contract is deployed
+	///  using uniquenetwork evm-migration pallet, or using other terms not
+	///  intended by pallet-evm
+	/// @dev Returns zero address if contract does not exists
+	/// @param contractAddress Contract to get owner of
+	/// @return address Owner of contract
+	/// @dev EVM selector for this function is: 0x5152b14c,
+	///  or in textual repr: contractOwner(address)
 	function contractOwner(address contractAddress)
 		public
 		view
@@ -47,11 +45,10 @@
 	}
 
 	/// Set sponsor.
-	///
 	/// @param contractAddress Contract for which a sponsor is being established.
 	/// @param sponsor User address who set as pending sponsor.
-	///
-	/// Selector: setSponsor(address,address) f01fba93
+	/// @dev EVM selector for this function is: 0xf01fba93,
+	///  or in textual repr: setSponsor(address,address)
 	function setSponsor(address contractAddress, address sponsor) public {
 		require(false, stub_error);
 		contractAddress;
@@ -62,8 +59,8 @@
 	/// Set contract as self sponsored.
 	///
 	/// @param contractAddress Contract for which a self sponsoring is being enabled.
-	///
-	/// Selector: selfSponsoredEnable(address) 89f7d9ae
+	/// @dev EVM selector for this function is: 0x89f7d9ae,
+	///  or in textual repr: selfSponsoredEnable(address)
 	function selfSponsoredEnable(address contractAddress) public {
 		require(false, stub_error);
 		contractAddress;
@@ -73,8 +70,8 @@
 	/// Remove sponsor.
 	///
 	/// @param contractAddress Contract for which a sponsorship is being removed.
-	///
-	/// Selector: removeSponsor(address) ef784250
+	/// @dev EVM selector for this function is: 0xef784250,
+	///  or in textual repr: removeSponsor(address)
 	function removeSponsor(address contractAddress) public {
 		require(false, stub_error);
 		contractAddress;
@@ -86,8 +83,8 @@
 	/// @dev Caller must be same that set via [`setSponsor`].
 	///
 	/// @param contractAddress Сontract for which need to confirm sponsorship.
-	///
-	/// Selector: confirmSponsorship(address) abc00001
+	/// @dev EVM selector for this function is: 0xabc00001,
+	///  or in textual repr: confirmSponsorship(address)
 	function confirmSponsorship(address contractAddress) public {
 		require(false, stub_error);
 		contractAddress;
@@ -98,8 +95,8 @@
 	///
 	/// @param contractAddress The contract for which a sponsor is requested.
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
-	///
-	/// Selector: getSponsor(address) 743fc745
+	/// @dev EVM selector for this function is: 0x743fc745,
+	///  or in textual repr: getSponsor(address)
 	function getSponsor(address contractAddress)
 		public
 		view
@@ -115,8 +112,8 @@
 	///
 	/// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
 	/// @return **true** if contract has confirmed sponsor.
-	///
-	/// Selector: hasSponsor(address) 97418603
+	/// @dev EVM selector for this function is: 0x97418603,
+	///  or in textual repr: hasSponsor(address)
 	function hasSponsor(address contractAddress) public view returns (bool) {
 		require(false, stub_error);
 		contractAddress;
@@ -128,8 +125,8 @@
 	///
 	/// @param contractAddress The contract for which the presence of a pending sponsor is checked.
 	/// @return **true** if contract has pending sponsor.
-	///
-	/// Selector: hasPendingSponsor(address) 39b9b242
+	/// @dev EVM selector for this function is: 0x39b9b242,
+	///  or in textual repr: hasPendingSponsor(address)
 	function hasPendingSponsor(address contractAddress)
 		public
 		view
@@ -141,7 +138,8 @@
 		return false;
 	}
 
-	/// Selector: sponsoringEnabled(address) 6027dc61
+	/// @dev EVM selector for this function is: 0x6027dc61,
+	///  or in textual repr: sponsoringEnabled(address)
 	function sponsoringEnabled(address contractAddress)
 		public
 		view
@@ -153,7 +151,8 @@
 		return false;
 	}
 
-	/// Selector: setSponsoringMode(address,uint8) fde8a560
+	/// @dev EVM selector for this function is: 0xfde8a560,
+	///  or in textual repr: setSponsoringMode(address,uint8)
 	function setSponsoringMode(address contractAddress, uint8 mode) public {
 		require(false, stub_error);
 		contractAddress;
@@ -161,11 +160,15 @@
 		dummy = 0;
 	}
 
-	/// Selector: sponsoringMode(address) b70c7267
-	function sponsoringMode(address contractAddress)
+	/// Get current contract sponsoring rate limit
+	/// @param contractAddress Contract to get sponsoring mode of
+	/// @return uint32 Amount of blocks between two sponsored transactions
+	/// @dev EVM selector for this function is: 0x610cfabd,
+	///  or in textual repr: getSponsoringRateLimit(address)
+	function getSponsoringRateLimit(address contractAddress)
 		public
 		view
-		returns (uint8)
+		returns (uint32)
 	{
 		require(false, stub_error);
 		contractAddress;
@@ -173,7 +176,14 @@
 		return 0;
 	}
 
-	/// Selector: setSponsoringRateLimit(address,uint32) 77b6c908
+	/// Set contract sponsoring rate limit
+	/// @dev Sponsoring rate limit - is a minimum amount of blocks that should
+	///  pass between two sponsored transactions
+	/// @param contractAddress Contract to change sponsoring rate limit of
+	/// @param rateLimit Target rate limit
+	/// @dev Only contract owner can change this setting
+	/// @dev EVM selector for this function is: 0x77b6c908,
+	///  or in textual repr: setSponsoringRateLimit(address,uint32)
 	function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
 		public
 	{
@@ -183,32 +193,53 @@
 		dummy = 0;
 	}
 
-	/// Selector: getSponsoringRateLimit(address) 610cfabd
-	function getSponsoringRateLimit(address contractAddress)
+	/// Is specified user present in contract allow list
+	/// @dev Contract owner always implicitly included
+	/// @param contractAddress Contract to check allowlist of
+	/// @param user User to check
+	/// @return bool Is specified users exists in contract allowlist
+	/// @dev EVM selector for this function is: 0x5c658165,
+	///  or in textual repr: allowed(address,address)
+	function allowed(address contractAddress, address user)
 		public
 		view
-		returns (uint32)
+		returns (bool)
 	{
 		require(false, stub_error);
 		contractAddress;
+		user;
 		dummy;
-		return 0;
+		return false;
 	}
 
-	/// Selector: allowed(address,address) 5c658165
-	function allowed(address contractAddress, address user)
-		public
-		view
-		returns (bool)
-	{
+	/// Toggle user presence in contract allowlist
+	/// @param contractAddress Contract to change allowlist of
+	/// @param user Which user presence should be toggled
+	/// @param isAllowed `true` if user should be allowed to be sponsored
+	///  or call this contract, `false` otherwise
+	/// @dev Only contract owner can change this setting
+	/// @dev EVM selector for this function is: 0x4706cc1c,
+	///  or in textual repr: toggleAllowed(address,address,bool)
+	function toggleAllowed(
+		address contractAddress,
+		address user,
+		bool isAllowed
+	) public {
 		require(false, stub_error);
 		contractAddress;
 		user;
-		dummy;
-		return false;
+		isAllowed;
+		dummy = 0;
 	}
 
-	/// Selector: allowlistEnabled(address) c772ef6c
+	/// Is this contract has allowlist access enabled
+	/// @dev Allowlist always can have users, and it is used for two purposes:
+	///  in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist
+	///  in case of allowlist access enabled, only users from allowlist may call this contract
+	/// @param contractAddress Contract to get allowlist access of
+	/// @return bool Is specified contract has allowlist access enabled
+	/// @dev EVM selector for this function is: 0xc772ef6c,
+	///  or in textual repr: allowlistEnabled(address)
 	function allowlistEnabled(address contractAddress)
 		public
 		view
@@ -220,24 +251,21 @@
 		return false;
 	}
 
-	/// Selector: toggleAllowlist(address,bool) 36de20f5
+	/// Toggle contract allowlist access
+	/// @param contractAddress Contract to change allowlist access of
+	/// @param enabled Should allowlist access to be enabled?
+	/// @dev EVM selector for this function is: 0x36de20f5,
+	///  or in textual repr: toggleAllowlist(address,bool)
 	function toggleAllowlist(address contractAddress, bool enabled) public {
 		require(false, stub_error);
 		contractAddress;
 		enabled;
 		dummy = 0;
 	}
+}
 
-	/// Selector: toggleAllowed(address,address,bool) 4706cc1c
-	function toggleAllowed(
-		address contractAddress,
-		address user,
-		bool isAllowed
-	) public {
-		require(false, stub_error);
-		contractAddress;
-		user;
-		isAllowed;
-		dummy = 0;
-	}
+/// @dev anonymous struct
+struct Tuple0 {
+	address field_0;
+	uint256 field_1;
 }
modifiedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -3,12 +3,6 @@
 
 pragma solidity >=0.8.0 <0.9.0;
 
-/// @dev anonymous struct
-struct Tuple0 {
-	address field_0;
-	uint256 field_1;
-}
-
 /// @dev common stubs holder
 interface Dummy {
 
@@ -18,39 +12,42 @@
 	function supportsInterface(bytes4 interfaceID) external view returns (bool);
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x6073d917
+/// @title Magic contract, which allows users to reconfigure other contracts
+/// @dev the ERC-165 identifier for this interface is 0xd77fab70
 interface ContractHelpers is Dummy, ERC165 {
-	/// Get contract ovner
-	///
-	/// @param contractAddress contract for which the owner is being determined.
-	/// @return Contract owner.
-	///
-	/// Selector: contractOwner(address) 5152b14c
+	/// Get user, which deployed specified contract
+	/// @dev May return zero address in case if contract is deployed
+	///  using uniquenetwork evm-migration pallet, or using other terms not
+	///  intended by pallet-evm
+	/// @dev Returns zero address if contract does not exists
+	/// @param contractAddress Contract to get owner of
+	/// @return address Owner of contract
+	/// @dev EVM selector for this function is: 0x5152b14c,
+	///  or in textual repr: contractOwner(address)
 	function contractOwner(address contractAddress)
 		external
 		view
 		returns (address);
 
 	/// Set sponsor.
-	///
 	/// @param contractAddress Contract for which a sponsor is being established.
 	/// @param sponsor User address who set as pending sponsor.
-	///
-	/// Selector: setSponsor(address,address) f01fba93
+	/// @dev EVM selector for this function is: 0xf01fba93,
+	///  or in textual repr: setSponsor(address,address)
 	function setSponsor(address contractAddress, address sponsor) external;
 
 	/// Set contract as self sponsored.
 	///
 	/// @param contractAddress Contract for which a self sponsoring is being enabled.
-	///
-	/// Selector: selfSponsoredEnable(address) 89f7d9ae
+	/// @dev EVM selector for this function is: 0x89f7d9ae,
+	///  or in textual repr: selfSponsoredEnable(address)
 	function selfSponsoredEnable(address contractAddress) external;
 
 	/// Remove sponsor.
 	///
 	/// @param contractAddress Contract for which a sponsorship is being removed.
-	///
-	/// Selector: removeSponsor(address) ef784250
+	/// @dev EVM selector for this function is: 0xef784250,
+	///  or in textual repr: removeSponsor(address)
 	function removeSponsor(address contractAddress) external;
 
 	/// Confirm sponsorship.
@@ -58,16 +55,16 @@
 	/// @dev Caller must be same that set via [`setSponsor`].
 	///
 	/// @param contractAddress Сontract for which need to confirm sponsorship.
-	///
-	/// Selector: confirmSponsorship(address) abc00001
+	/// @dev EVM selector for this function is: 0xabc00001,
+	///  or in textual repr: confirmSponsorship(address)
 	function confirmSponsorship(address contractAddress) external;
 
 	/// Get current sponsor.
 	///
 	/// @param contractAddress The contract for which a sponsor is requested.
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
-	///
-	/// Selector: getSponsor(address) 743fc745
+	/// @dev EVM selector for this function is: 0x743fc745,
+	///  or in textual repr: getSponsor(address)
 	function getSponsor(address contractAddress)
 		external
 		view
@@ -77,65 +74,102 @@
 	///
 	/// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
 	/// @return **true** if contract has confirmed sponsor.
-	///
-	/// Selector: hasSponsor(address) 97418603
+	/// @dev EVM selector for this function is: 0x97418603,
+	///  or in textual repr: hasSponsor(address)
 	function hasSponsor(address contractAddress) external view returns (bool);
 
 	/// Check tat contract has pending sponsor.
 	///
 	/// @param contractAddress The contract for which the presence of a pending sponsor is checked.
 	/// @return **true** if contract has pending sponsor.
-	///
-	/// Selector: hasPendingSponsor(address) 39b9b242
+	/// @dev EVM selector for this function is: 0x39b9b242,
+	///  or in textual repr: hasPendingSponsor(address)
 	function hasPendingSponsor(address contractAddress)
 		external
 		view
 		returns (bool);
 
-	/// Selector: sponsoringEnabled(address) 6027dc61
+	/// @dev EVM selector for this function is: 0x6027dc61,
+	///  or in textual repr: sponsoringEnabled(address)
 	function sponsoringEnabled(address contractAddress)
 		external
 		view
 		returns (bool);
 
-	/// Selector: setSponsoringMode(address,uint8) fde8a560
+	/// @dev EVM selector for this function is: 0xfde8a560,
+	///  or in textual repr: setSponsoringMode(address,uint8)
 	function setSponsoringMode(address contractAddress, uint8 mode) external;
 
-	/// Selector: sponsoringMode(address) b70c7267
-	function sponsoringMode(address contractAddress)
+	/// Get current contract sponsoring rate limit
+	/// @param contractAddress Contract to get sponsoring mode of
+	/// @return uint32 Amount of blocks between two sponsored transactions
+	/// @dev EVM selector for this function is: 0x610cfabd,
+	///  or in textual repr: getSponsoringRateLimit(address)
+	function getSponsoringRateLimit(address contractAddress)
 		external
 		view
-		returns (uint8);
+		returns (uint32);
 
-	/// Selector: setSponsoringRateLimit(address,uint32) 77b6c908
+	/// Set contract sponsoring rate limit
+	/// @dev Sponsoring rate limit - is a minimum amount of blocks that should
+	///  pass between two sponsored transactions
+	/// @param contractAddress Contract to change sponsoring rate limit of
+	/// @param rateLimit Target rate limit
+	/// @dev Only contract owner can change this setting
+	/// @dev EVM selector for this function is: 0x77b6c908,
+	///  or in textual repr: setSponsoringRateLimit(address,uint32)
 	function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
 		external;
 
-	/// Selector: getSponsoringRateLimit(address) 610cfabd
-	function getSponsoringRateLimit(address contractAddress)
-		external
-		view
-		returns (uint32);
-
-	/// Selector: allowed(address,address) 5c658165
+	/// Is specified user present in contract allow list
+	/// @dev Contract owner always implicitly included
+	/// @param contractAddress Contract to check allowlist of
+	/// @param user User to check
+	/// @return bool Is specified users exists in contract allowlist
+	/// @dev EVM selector for this function is: 0x5c658165,
+	///  or in textual repr: allowed(address,address)
 	function allowed(address contractAddress, address user)
 		external
 		view
 		returns (bool);
 
-	/// Selector: allowlistEnabled(address) c772ef6c
+	/// Toggle user presence in contract allowlist
+	/// @param contractAddress Contract to change allowlist of
+	/// @param user Which user presence should be toggled
+	/// @param isAllowed `true` if user should be allowed to be sponsored
+	///  or call this contract, `false` otherwise
+	/// @dev Only contract owner can change this setting
+	/// @dev EVM selector for this function is: 0x4706cc1c,
+	///  or in textual repr: toggleAllowed(address,address,bool)
+	function toggleAllowed(
+		address contractAddress,
+		address user,
+		bool isAllowed
+	) external;
+
+	/// Is this contract has allowlist access enabled
+	/// @dev Allowlist always can have users, and it is used for two purposes:
+	///  in case of allowlist sponsoring mode, users will be sponsored if they exist in allowlist
+	///  in case of allowlist access enabled, only users from allowlist may call this contract
+	/// @param contractAddress Contract to get allowlist access of
+	/// @return bool Is specified contract has allowlist access enabled
+	/// @dev EVM selector for this function is: 0xc772ef6c,
+	///  or in textual repr: allowlistEnabled(address)
 	function allowlistEnabled(address contractAddress)
 		external
 		view
 		returns (bool);
 
-	/// Selector: toggleAllowlist(address,bool) 36de20f5
+	/// Toggle contract allowlist access
+	/// @param contractAddress Contract to change allowlist access of
+	/// @param enabled Should allowlist access to be enabled?
+	/// @dev EVM selector for this function is: 0x36de20f5,
+	///  or in textual repr: toggleAllowlist(address,bool)
 	function toggleAllowlist(address contractAddress, bool enabled) external;
+}
 
-	/// Selector: toggleAllowed(address,address,bool) 4706cc1c
-	function toggleAllowed(
-		address contractAddress,
-		address user,
-		bool isAllowed
-	) external;
+/// @dev anonymous struct
+struct Tuple0 {
+	address field_0;
+	uint256 field_1;
 }
modifiedtests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/util/contractHelpersAbi.json
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -197,19 +197,6 @@
   },
   {
     "inputs": [
-      {
-        "internalType": "address",
-        "name": "contractAddress",
-        "type": "address"
-      }
-    ],
-    "name": "sponsoringMode",
-    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
-    "stateMutability": "view",
-    "type": "function"
-  },
-  {
-    "inputs": [
       { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
     ],
     "name": "supportsInterface",