difftreelog
Merge branch 'feature/app-staking' of https://github.com/UniqueNetwork/unique-chain into feature/app-staking
in: master
11 files changed
Cargo.lockdiffbeforeafterboth5735name = "pallet-evm-contract-helpers"5735name = "pallet-evm-contract-helpers"5736version = "0.2.0"5736version = "0.2.0"5737dependencies = [5737dependencies = [5738 "ethereum",5738 "evm-coder",5739 "evm-coder",5739 "fp-evm-mapping",5740 "fp-evm-mapping",5740 "frame-support",5741 "frame-support",pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth9 "derive",9 "derive",10] }10] }11log = { default-features = false, version = "0.4.14" }11log = { default-features = false, version = "0.4.14" }12ethereum = { version = "0.12.0", default-features = false }121313# Substrate14# Substrate14frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }15frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth181819use core::marker::PhantomData;19use core::marker::PhantomData;20use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};20use evm_coder::{21 abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,22};21use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};23use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};22use pallet_evm::{24use pallet_evm::{33use up_sponsorship::SponsorshipHandler;35use up_sponsorship::SponsorshipHandler;34use sp_std::vec::Vec;36use sp_std::vec::Vec;3738/// Pallet events.39#[derive(ToLog)]40pub enum ContractHelpersEvents {41 /// Contract sponsor was set.42 ContractSponsorSet {43 /// Contract address of the affected collection.44 #[indexed]45 contract_address: address,46 /// New sponsor address.47 sponsor: address,48 },4950 /// New sponsor was confirm.51 ContractSponsorshipConfirmed {52 /// Contract address of the affected collection.53 #[indexed]54 contract_address: address,55 /// New sponsor address.56 sponsor: address,57 },5859 /// Collection sponsor was removed.60 ContractSponsorRemoved {61 /// Contract address of the affected collection.62 #[indexed]63 contract_address: address,64 },65}356636/// See [`ContractHelpersCall`]67/// See [`ContractHelpersCall`]37pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);68pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);46}77}477848/// @title Magic contract, which allows users to reconfigure other contracts79/// @title Magic contract, which allows users to reconfigure other contracts49#[solidity_interface(name = ContractHelpers)]80#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents))]50impl<T: Config> ContractHelpers<T>81impl<T: Config> ContractHelpers<T>51where82where52 T::AccountId: AsRef<[u8; 32]>,83 T::AccountId: AsRef<[u8; 32]>,91 self.recorder().consume_sload()?;122 self.recorder().consume_sload()?;92 self.recorder().consume_sstore()?;123 self.recorder().consume_sstore()?;9312494 Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)125 Pallet::<T>::force_set_sponsor(126 &T::CrossAccountId::from_eth(caller),127 contract_address,128 &T::CrossAccountId::from_eth(contract_address),129 )95 .map_err(dispatch_to_evm::<T>)?;130 .map_err(dispatch_to_evm::<T>)?;96131pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth161617#![doc = include_str!("../README.md")]17#![doc = include_str!("../README.md")]18#![cfg_attr(not(feature = "std"), no_std)]18#![cfg_attr(not(feature = "std"), no_std)]19#![deny(missing_docs)]19#![warn(missing_docs)]202021use codec::{Decode, Encode, MaxEncodedLen};21use codec::{Decode, Encode, MaxEncodedLen};22pub use pallet::*;22pub use pallet::*;27#[frame_support::pallet]27#[frame_support::pallet]28pub mod pallet {28pub mod pallet {29 pub use super::*;29 pub use super::*;30 use crate::eth::ContractHelpersEvents;30 use frame_support::pallet_prelude::*;31 use frame_support::pallet_prelude::*;31 use pallet_evm_coder_substrate::DispatchResult;32 use pallet_evm_coder_substrate::DispatchResult;32 use sp_core::H160;33 use sp_core::H160;33 use pallet_evm::account::CrossAccountId;34 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};34 use up_data_structs::SponsorshipState;35 use up_data_structs::SponsorshipState;36 use evm_coder::ToLog;353736 #[pallet::config]38 #[pallet::config]37 pub trait Config:39 pub trait Config:38 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config40 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config39 {41 {42 /// Overarching event type.43 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;4440 /// Address, under which magic contract will be available45 /// Address, under which magic contract will be available41 type ContractAddress: Get<H160>;46 type ContractAddress: Get<H160>;150 QueryKind = ValueQuery,156 QueryKind = ValueQuery,151 >;157 >;158159 #[pallet::event]160 #[pallet::generate_deposit(pub fn deposit_event)]161 pub enum Event<T: Config> {162 /// Contract sponsor was set.163 ContractSponsorSet(164 /// Contract address of the affected collection.165 H160,166 /// New sponsor address.167 T::AccountId,168 ),169170 /// New sponsor was confirm.171 ContractSponsorshipConfirmed(172 /// Contract address of the affected collection.173 H160,174 /// New sponsor address.175 T::AccountId,176 ),177178 /// Collection sponsor was removed.179 ContractSponsorRemoved(180 /// Contract address of the affected collection.181 H160,182 ),183 }152184153 impl<T: Config> Pallet<T> {185 impl<T: Config> Pallet<T> {154 /// Get contract owner.186 /// Get contract owner.170 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),202 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),171 );203 );204205 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(206 contract,207 sponsor.as_sub().clone(),208 ));209 <PalletEvm<T>>::deposit_log(210 ContractHelpersEvents::ContractSponsorSet {211 contract_address: contract,212 sponsor: *sponsor.as_eth(),213 }214 .to_log(contract),215 );172 Ok(())216 Ok(())173 }217 }174218175 /// Set `contract` as self sponsored.219 /// Set sponsor as already confirmed.176 ///220 ///177 /// `sender` must be owner of contract.221 /// `sender` must be owner of contract.178 pub fn self_sponsored_enable(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {222 pub fn force_set_sponsor(223 sender: &T::CrossAccountId,224 contract_address: H160,225 sponsor: &T::CrossAccountId,226 ) -> DispatchResult {179 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;227 Pallet::<T>::ensure_owner(contract_address, *sender.as_eth())?;180 Sponsoring::<T>::insert(228 Sponsoring::<T>::insert(181 contract,229 contract_address,182 SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(230 SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(183 contract,231 contract_address,184 )),232 )),185 );233 );234235 let eth_sponsor = *sponsor.as_eth();236 let sub_sponsor = sponsor.as_sub().clone();237238 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(239 contract_address,240 sub_sponsor.clone(),241 ));242 <PalletEvm<T>>::deposit_log(243 ContractHelpersEvents::ContractSponsorSet {244 contract_address,245 sponsor: eth_sponsor,246 }247 .to_log(contract_address),248 );249250 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(251 contract_address,252 sub_sponsor,253 ));254 <PalletEvm<T>>::deposit_log(255 ContractHelpersEvents::ContractSponsorshipConfirmed {256 contract_address,257 sponsor: eth_sponsor,258 }259 .to_log(contract_address),260 );261186 Ok(())262 Ok(())187 }263 }188264189 /// Remove sponsor for `contract`.265 /// Remove sponsor for `contract`.190 ///266 ///191 /// `sender` must be owner of contract.267 /// `sender` must be owner of contract.192 pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {268 pub fn remove_sponsor(sender: &T::CrossAccountId, contract_address: H160) -> DispatchResult {193 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;269 Pallet::<T>::ensure_owner(contract_address, *sender.as_eth())?;194 Sponsoring::<T>::remove(contract);270 Sponsoring::<T>::remove(contract_address);271272 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorRemoved(contract_address));273 <PalletEvm<T>>::deposit_log(274 ContractHelpersEvents::ContractSponsorRemoved { contract_address }.to_log(contract_address),275 );276195 Ok(())277 Ok(())196 }278 }197279198 /// Confirm sponsorship.280 /// Confirm sponsorship.199 ///281 ///200 /// `sender` must be same that set via [`set_sponsor`].282 /// `sender` must be same that set via [`set_sponsor`].201 pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {283 pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract_address: H160) -> DispatchResult {202 match Sponsoring::<T>::get(contract) {284 match Sponsoring::<T>::get(contract_address) {203 SponsorshipState::Unconfirmed(sponsor) => {285 SponsorshipState::Unconfirmed(sponsor) => {204 ensure!(sponsor == *sender, Error::<T>::NoPermission);286 ensure!(sponsor == *sender, Error::<T>::NoPermission);287 let eth_sponsor = *sponsor.as_eth();288 let sub_sponsor = sponsor.as_sub().clone();205 Sponsoring::<T>::insert(289 Sponsoring::<T>::insert(206 contract,290 contract_address,207 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),291 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),208 );292 );293294 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(295 contract_address,296 sub_sponsor,297 ));298 <PalletEvm<T>>::deposit_log(299 ContractHelpersEvents::ContractSponsorshipConfirmed {300 contract_address,301 sponsor: eth_sponsor,302 }303 .to_log(contract_address),304 );305209 Ok(())306 Ok(())210 }307 }pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth21 }21 }22}22}2324/// @dev inlined interface25contract ContractHelpersEvents {26 event ContractSponsorSet(address indexed contractAddress, address sponsor);27 event ContractSponsorshipConfirmed(28 address indexed contractAddress,29 address sponsor30 );31 event ContractSponsorRemoved(address indexed contractAddress);32}233324/// @title Magic contract, which allows users to reconfigure other contracts34/// @title Magic contract, which allows users to reconfigure other contracts25/// @dev the ERC-165 identifier for this interface is 0xd77fab7035/// @dev the ERC-165 identifier for this interface is 0xd77fab7026contract ContractHelpers is Dummy, ERC165 {36contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents {27 /// Get user, which deployed specified contract37 /// Get user, which deployed specified contract28 /// @dev May return zero address in case if contract is deployed38 /// @dev May return zero address in case if contract is deployed29 /// using uniquenetwork evm-migration pallet, or using other terms not39 /// using uniquenetwork evm-migration pallet, or using other terms notruntime/common/config/ethereum.rsdiffbeforeafterboth112}112}113113114impl pallet_evm_contract_helpers::Config for Runtime {114impl pallet_evm_contract_helpers::Config for Runtime {115 type Event = Event;115 type ContractAddress = HelpersContractAddress;116 type ContractAddress = HelpersContractAddress;116 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;117 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;117}118}runtime/common/construct_runtime/mod.rsdiffbeforeafterboth85 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,85 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,868687 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,87 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,88 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,88 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage, Event<T>} = 151,89 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,89 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,90 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,90 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,91 }91 }tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth12 function supportsInterface(bytes4 interfaceID) external view returns (bool);12 function supportsInterface(bytes4 interfaceID) external view returns (bool);13}13}1415/// @dev inlined interface16interface ContractHelpersEvents {17 event ContractSponsorSet(address indexed contractAddress, address sponsor);18 event ContractSponsorshipConfirmed(19 address indexed contractAddress,20 address sponsor21 );22 event ContractSponsorRemoved(address indexed contractAddress);23}142415/// @title Magic contract, which allows users to reconfigure other contracts25/// @title Magic contract, which allows users to reconfigure other contracts16/// @dev the ERC-165 identifier for this interface is 0xd77fab7026/// @dev the ERC-165 identifier for this interface is 0xd77fab7017interface ContractHelpers is Dummy, ERC165 {27interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents {18 /// Get user, which deployed specified contract28 /// Get user, which deployed specified contract19 /// @dev May return zero address in case if contract is deployed29 /// @dev May return zero address in case if contract is deployed20 /// using uniquenetwork evm-migration pallet, or using other terms not30 /// using uniquenetwork evm-migration pallet, or using other terms nottests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth24 SponsoringMode,24 SponsoringMode,25 createEthAccount,25 createEthAccount,26 ethBalanceViaSub,26 ethBalanceViaSub,27 normalizeEvents,27} from './util/helpers';28} from './util/helpers';282929describe('Sponsoring EVM contracts', () => {30describe('Sponsoring EVM contracts', () => {36 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;37 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;37 });38 });3940 itWeb3.only('Set self sponsored events', async ({api, web3, privateKeyWrapper}) => {41 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);42 const flipper = await deployFlipper(web3, owner);43 const helpers = contractHelpers(web3, owner);44 45 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();46 const events = normalizeEvents(result.events);47 expect(events).to.be.deep.equal([48 {49 address: flipper.options.address,50 event: 'ContractSponsorSet',51 args: {52 contractAddress: flipper.options.address,53 sponsor: flipper.options.address,54 },55 },56 {57 address: flipper.options.address,58 event: 'ContractSponsorshipConfirmed',59 args: {60 contractAddress: flipper.options.address,61 sponsor: flipper.options.address,62 },63 },64 ]);65 });386639 itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {67 itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {40 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);68 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);75 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;103 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;76 });104 });77 105 106 itWeb3('Set sponsor event', async ({api, web3, privateKeyWrapper}) => {107 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);108 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);109 const flipper = await deployFlipper(web3, owner);110 const helpers = contractHelpers(web3, owner);111 112 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();113 const events = normalizeEvents(result.events);114 expect(events).to.be.deep.equal([115 {116 address: flipper.options.address,117 event: 'ContractSponsorSet',118 args: {119 contractAddress: flipper.options.address,120 sponsor: sponsor,121 },122 },123 ]);124 });125 78 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {126 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {79 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);127 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;145 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;98 });146 });147148 itWeb3('Confirm sponsorship event', async ({api, web3, privateKeyWrapper}) => {149 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);150 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);151 const flipper = await deployFlipper(web3, owner);152 const helpers = contractHelpers(web3, owner);153 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;154 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});155 const events = normalizeEvents(result.events);156 expect(events).to.be.deep.equal([157 {158 address: flipper.options.address,159 event: 'ContractSponsorshipConfirmed',160 args: {161 contractAddress: flipper.options.address,162 sponsor: sponsor,163 },164 },165 ]);166 });99167100 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {168 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {101 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);169 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);160 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;228 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;161 });229 });230231 itWeb3('Remove sponsor event', async ({api, web3, privateKeyWrapper}) => {232 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);233 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);234 const flipper = await deployFlipper(web3, owner);235 const helpers = contractHelpers(web3, owner);236237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();238 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});239 240 const result = await helpers.methods.removeSponsor(flipper.options.address).send();241 const events = normalizeEvents(result.events);242 expect(events).to.be.deep.equal([243 {244 address: flipper.options.address,245 event: 'ContractSponsorRemoved',246 args: {247 contractAddress: flipper.options.address,248 },249 },250 ]);251 });162252163 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {253 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {164 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);254 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);tests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth1[1[2 {3 "anonymous": false,4 "inputs": [5 {6 "indexed": true,7 "internalType": "address",8 "name": "contractAddress",9 "type": "address"10 }11 ],12 "name": "ContractSponsorRemoved",13 "type": "event"14 },15 {16 "anonymous": false,17 "inputs": [18 {19 "indexed": true,20 "internalType": "address",21 "name": "contractAddress",22 "type": "address"23 },24 {25 "indexed": false,26 "internalType": "address",27 "name": "sponsor",28 "type": "address"29 }30 ],31 "name": "ContractSponsorSet",32 "type": "event"33 },34 {35 "anonymous": false,36 "inputs": [37 {38 "indexed": true,39 "internalType": "address",40 "name": "contractAddress",41 "type": "address"42 },43 {44 "indexed": false,45 "internalType": "address",46 "name": "sponsor",47 "type": "address"48 }49 ],50 "name": "ContractSponsorshipConfirmed",51 "type": "event"52 },2 {53 {3 "inputs": [54 "inputs": [4 {55 {