difftreelog
fix Return sponsor address in canonical form.
in: master
4 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2345,7 +2345,7 @@
[[package]]
name = "fc-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"async-trait",
"fc-db",
@@ -2364,7 +2364,7 @@
[[package]]
name = "fc-db"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"fp-storage",
"kvdb-rocksdb",
@@ -2380,7 +2380,7 @@
[[package]]
name = "fc-mapping-sync"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"fc-db",
"fp-consensus",
@@ -2397,7 +2397,7 @@
[[package]]
name = "fc-rpc"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2437,7 +2437,7 @@
[[package]]
name = "fc-rpc-core"
version = "1.1.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2578,7 +2578,7 @@
[[package]]
name = "fp-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"parity-scale-codec 3.1.5",
@@ -2590,7 +2590,7 @@
[[package]]
name = "fp-evm"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"evm",
"frame-support",
@@ -2604,7 +2604,7 @@
[[package]]
name = "fp-evm-mapping"
version = "0.1.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"frame-support",
"sp-core",
@@ -2613,7 +2613,7 @@
[[package]]
name = "fp-rpc"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2630,7 +2630,7 @@
[[package]]
name = "fp-self-contained"
version = "1.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"frame-support",
@@ -2646,7 +2646,7 @@
[[package]]
name = "fp-storage"
version = "2.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"parity-scale-codec 3.1.5",
]
@@ -5445,7 +5445,7 @@
[[package]]
name = "pallet-base-fee"
version = "1.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"fp-evm",
"frame-support",
@@ -5660,7 +5660,7 @@
[[package]]
name = "pallet-ethereum"
version = "4.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"ethereum",
"ethereum-types",
@@ -5689,7 +5689,7 @@
[[package]]
name = "pallet-evm"
version = "6.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#64915c0986fcf2bbe942794b838c0cf359c93c21"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
dependencies = [
"evm",
"fp-evm",
@@ -12130,7 +12130,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
"digest 0.10.3",
"rand 0.8.5",
"static_assertions",
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/>.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 Contract_address 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 contract_address 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 Pallet::<T>::set_sponsor(69 &T::CrossAccountId::from_eth(caller),70 contract_address,71 &T::CrossAccountId::from_eth(sponsor),72 )73 .map_err(dispatch_to_evm::<T>)?;7475 self.recorder().consume_sload()?;76 self.recorder().consume_sstore()?;77 78 Ok(())79 }8081 /// Set contract as self sponsored.82 ///83 /// @param contract_address Contract for which a self sponsoring is being enabled.84 fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {85 Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)86 .map_err(dispatch_to_evm::<T>)?;87 88 self.recorder().consume_sload()?;89 self.recorder().consume_sstore()?;9091 Ok(())92 }9394 /// Remove sponsor.95 ///96 /// @param contract_address Contract for which a sponsorship is being removed.97 fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {98 Pallet::<T>::remove_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)99 .map_err(dispatch_to_evm::<T>)?;100101 self.recorder().consume_sload()?;102 self.recorder().consume_sstore()?;103 104 Ok(())105 }106107 /// Confirm sponsorship.108 ///109 /// @dev Caller must be same that set via [`set_sponsor`].110 ///111 /// @param contract_address Сontract for which need to confirm sponsorship.112 fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {113 Pallet::<T>::confirm_sponsorship(&T::CrossAccountId::from_eth(caller), contract_address)114 .map_err(dispatch_to_evm::<T>)?;115116 self.recorder().consume_sload()?;117 self.recorder().consume_sstore()?;118119 Ok(())120 }121122 /// Get current sponsor.123 ///124 /// @param contract_address 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 sponsor_sub = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);130 Ok((*sponsor.as_eth(), sponsor_sub))131 }132133 /// Check tat contract has confirmed sponsor.134 ///135 /// @param contract_address The contract for which the presence of a confirmed sponsor is checked.136 /// @return **true** if contract has confirmed sponsor.137 fn has_sponsor(&self, contract_address: address) -> Result<bool> {138 Ok(Pallet::<T>::get_sponsor(contract_address).is_some())139 }140141 /// Check tat contract has pending sponsor.142 ///143 /// @param contract_address The contract for which the presence of a pending sponsor is checked.144 /// @return **true** if contract has pending sponsor.145 fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {146 Ok(match Sponsoring::<T>::get(contract_address) {147 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false,148 SponsorshipState::Unconfirmed(_) => true,149 })150 }151152 fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {153 Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)154 }155156 fn set_sponsoring_mode(157 &mut self,158 caller: caller,159 contract_address: address,160 mode: uint8,161 ) -> Result<void> {162 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;163 let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;164 <Pallet<T>>::set_sponsoring_mode(contract_address, mode);165166 self.recorder().consume_sload()?;167 self.recorder().consume_sstore()?;168169 Ok(())170 }171172 fn sponsoring_mode(&self, contract_address: address) -> Result<uint8> {173 Ok(<Pallet<T>>::sponsoring_mode(contract_address).to_eth())174 }175176 fn set_sponsoring_rate_limit(177 &mut self,178 caller: caller,179 contract_address: address,180 rate_limit: uint32,181 ) -> Result<void> {182 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;183 <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());184185 self.recorder().consume_sload()?;186 self.recorder().consume_sstore()?;187188 Ok(())189 }190191 fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {192 Ok(<SponsoringRateLimit<T>>::get(contract_address)193 .try_into()194 .map_err(|_| "rate limit > u32::MAX")?)195 }196197 fn allowed(&self, contract_address: address, user: address) -> Result<bool> {198 self.0.consume_sload()?;199 Ok(<Pallet<T>>::allowed(contract_address, user))200 }201202 fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {203 Ok(<AllowlistEnabled<T>>::get(contract_address))204 }205206 fn toggle_allowlist(207 &mut self,208 caller: caller,209 contract_address: address,210 enabled: bool,211 ) -> Result<void> {212 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;213 <Pallet<T>>::toggle_allowlist(contract_address, enabled);214215 self.recorder().consume_sload()?;216 self.recorder().consume_sstore()?;217218 Ok(())219 }220221 fn toggle_allowed(222 &mut self,223 caller: caller,224 contract_address: address,225 user: address,226 allowed: bool,227 ) -> Result<void> {228 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;229 <Pallet<T>>::toggle_allowed(contract_address, user, allowed);230231 self.recorder().consume_sload()?;232 self.recorder().consume_sstore()?;233 234 Ok(())235 }236}237238pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);239impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T>240where241 T::AccountId: AsRef<[u8; 32]>,242{243 fn is_reserved(contract: &sp_core::H160) -> bool {244 contract == &T::ContractAddress::get()245 }246247 fn is_used(contract: &sp_core::H160) -> bool {248 contract == &T::ContractAddress::get()249 }250251 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {252 // TODO: Extract to another OnMethodCall handler253 if <AllowlistEnabled<T>>::get(handle.code_address())254 && !<Pallet<T>>::allowed(handle.code_address(), handle.context().caller)255 {256 return Some(Err(PrecompileFailure::Revert {257 exit_status: ExitRevert::Reverted,258 output: {259 let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));260 writer.string("Target contract is allowlisted");261 writer.finish()262 },263 }));264 }265266 if handle.code_address() != T::ContractAddress::get() {267 return None;268 }269270 let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));271 pallet_evm_coder_substrate::call(handle, helpers)272 }273274 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {275 (contract == &T::ContractAddress::get())276 .then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())277 }278}279280pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);281impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {282 fn on_create(owner: H160, contract: H160) {283 <Owner<T>>::insert(contract, owner);284 }285}286287pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);288impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>289 for HelpersContractSponsoring<T>290{291 fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {292 let (contract, _) = call;293 let mode = <Pallet<T>>::sponsoring_mode(*contract);294 if mode == SponsoringModeT::Disabled {295 return None;296 }297298 let sponsor = match <Pallet<T>>::get_sponsor(*contract) {299 Some(sponsor) => sponsor,300 None => return None,301 };302303 if mode == SponsoringModeT::Allowlisted && !<Pallet<T>>::allowed(*contract, *who.as_eth()) {304 return None;305 }306 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;307308 if let Some(last_tx_block) = <SponsorBasket<T>>::get(contract, who.as_eth()) {309 let limit = <SponsoringRateLimit<T>>::get(contract);310311 let timeout = last_tx_block + limit;312 if block_number < timeout {313 return None;314 }315 }316317 <SponsorBasket<T>>::insert(contract, who.as_eth(), block_number);318319 Some(sponsor)320 }321}322323generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);324generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);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 Contract_address 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 contract_address 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 Pallet::<T>::set_sponsor(69 &T::CrossAccountId::from_eth(caller),70 contract_address,71 &T::CrossAccountId::from_eth(sponsor),72 )73 .map_err(dispatch_to_evm::<T>)?;7475 self.recorder().consume_sload()?;76 self.recorder().consume_sstore()?;77 78 Ok(())79 }8081 /// Set contract as self sponsored.82 ///83 /// @param contract_address Contract for which a self sponsoring is being enabled.84 fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {85 Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)86 .map_err(dispatch_to_evm::<T>)?;87 88 self.recorder().consume_sload()?;89 self.recorder().consume_sstore()?;9091 Ok(())92 }9394 /// Remove sponsor.95 ///96 /// @param contract_address Contract for which a sponsorship is being removed.97 fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {98 Pallet::<T>::remove_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)99 .map_err(dispatch_to_evm::<T>)?;100101 self.recorder().consume_sload()?;102 self.recorder().consume_sstore()?;103 104 Ok(())105 }106107 /// Confirm sponsorship.108 ///109 /// @dev Caller must be same that set via [`set_sponsor`].110 ///111 /// @param contract_address Сontract for which need to confirm sponsorship.112 fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {113 Pallet::<T>::confirm_sponsorship(&T::CrossAccountId::from_eth(caller), contract_address)114 .map_err(dispatch_to_evm::<T>)?;115116 self.recorder().consume_sload()?;117 self.recorder().consume_sstore()?;118119 Ok(())120 }121122 /// Get current sponsor.123 ///124 /// @param contract_address 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 contract_address 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 contract_address 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 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;169 let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;170 <Pallet<T>>::set_sponsoring_mode(contract_address, mode);171172 self.recorder().consume_sload()?;173 self.recorder().consume_sstore()?;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 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;189 <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());190191 self.recorder().consume_sload()?;192 self.recorder().consume_sstore()?;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 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;219 <Pallet<T>>::toggle_allowlist(contract_address, enabled);220221 self.recorder().consume_sload()?;222 self.recorder().consume_sstore()?;223224 Ok(())225 }226227 fn toggle_allowed(228 &mut self,229 caller: caller,230 contract_address: address,231 user: address,232 allowed: bool,233 ) -> Result<void> {234 <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;235 <Pallet<T>>::toggle_allowed(contract_address, user, allowed);236237 self.recorder().consume_sload()?;238 self.recorder().consume_sstore()?;239 240 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, _) = call;299 let mode = <Pallet<T>>::sponsoring_mode(*contract);300 if mode == SponsoringModeT::Disabled {301 return None;302 }303304 let sponsor = match <Pallet<T>>::get_sponsor(*contract) {305 Some(sponsor) => sponsor,306 None => return None,307 };308309 if mode == SponsoringModeT::Allowlisted && !<Pallet<T>>::allowed(*contract, *who.as_eth()) {310 return None;311 }312 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;313314 if let Some(last_tx_block) = <SponsorBasket<T>>::get(contract, who.as_eth()) {315 let limit = <SponsoringRateLimit<T>>::get(contract);316317 let timeout = last_tx_block + limit;318 if block_number < timeout {319 return None;320 }321 }322323 <SponsorBasket<T>>::insert(contract, who.as_eth(), block_number);324325 Some(sponsor)326 }327}328329generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);330generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);runtime/tests/src/lib.rsdiffbeforeafterboth--- a/runtime/tests/src/lib.rs
+++ b/runtime/tests/src/lib.rs
@@ -167,7 +167,7 @@
}
#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo, MaxEncodedLen)]
-pub struct TestCrossAccountId(u64, sp_core::H160);
+pub struct TestCrossAccountId(u64, sp_core::H160, bool);
impl CrossAccountId<u64> for TestCrossAccountId {
fn as_sub(&self) -> &u64 {
&self.0
@@ -178,17 +178,20 @@
fn from_sub(sub: u64) -> Self {
let mut eth = [0; 20];
eth[12..20].copy_from_slice(&sub.to_be_bytes());
- Self(sub, sp_core::H160(eth))
+ Self(sub, sp_core::H160(eth), true)
}
fn from_eth(eth: sp_core::H160) -> Self {
let mut sub_raw = [0; 8];
sub_raw.copy_from_slice(ð.0[0..8]);
let sub = u64::from_be_bytes(sub_raw);
- Self(sub, eth)
+ Self(sub, eth, false)
}
fn conv_eq(&self, other: &Self) -> bool {
self.as_sub() == other.as_sub()
}
+ fn is_canonical_substrate(&self) -> bool {
+ self.2
+ }
}
impl Default for TestCrossAccountId {
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -129,8 +129,7 @@
const result = await helpers.methods.getSponsor(flipper.options.address).call();
expect(result[0]).to.be.eq(flipper.options.address);
- const sponsorSub = api.registry.createType('AccountId', '0x' + BigInt(result[1]).toString(16).padStart(64, '0')).toJSON();
- expect(sponsorSub).to.be.eq(evmToAddress(flipper.options.address));
+ expect(result[1]).to.be.eq('0');
});
itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {
@@ -144,8 +143,7 @@
const result = await helpers.methods.getSponsor(flipper.options.address).call();
expect(result[0]).to.be.eq(sponsor);
- const sponsorSub = api.registry.createType('AccountId', '0x' + BigInt(result[1]).toString(16).padStart(64, '0')).toJSON();
- expect(sponsorSub).to.be.eq(evmToAddress(sponsor));
+ expect(result[1]).to.be.eq('0');
});
itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {