From 59a7323b3e787b37bd185cfa42f77fca49b63fe6 Mon Sep 17 00:00:00 2001 From: Zachary Frederick Date: Thu, 24 Aug 2023 10:00:40 -0400 Subject: [PATCH] Introduce the set_gate_contract() extrinsic in preparation for request_collect_coins_v2 --- .../src/test/collect-coins.test.ts | 2 +- .../test/set-collect-coins-contract.test.ts | 2 +- pallets/creditcoin/src/benchmarking.rs | 7 ++- pallets/creditcoin/src/lib.rs | 25 +++++++++-- .../creditcoin/src/ocw/tasks/collect_coins.rs | 34 +++++++------- pallets/creditcoin/src/tests.rs | 45 +++++++++++++++++++ pallets/creditcoin/src/types.rs | 2 +- pallets/creditcoin/src/types/collect_coins.rs | 6 +-- pallets/creditcoin/src/weights.rs | 4 ++ 9 files changed, 100 insertions(+), 27 deletions(-) diff --git a/integration-tests/src/test/collect-coins.test.ts b/integration-tests/src/test/collect-coins.test.ts index 89fb27d431..a3dceb254a 100644 --- a/integration-tests/src/test/collect-coins.test.ts +++ b/integration-tests/src/test/collect-coins.test.ts @@ -44,7 +44,7 @@ describe('CollectCoins', (): void => { collector = (global as any).CREDITCOIN_CREATE_SIGNER(keyring, 'lender'); /* eslint-disable @typescript-eslint/naming-convention */ - const contract = api.createType('PalletCreditcoinOcwTasksCollectCoinsGCreContract', { + const contract = api.createType('PalletCreditcoinOcwTasksCollectCoinsDeployedContract', { address: (global as any).CREDITCOIN_CTC_CONTRACT_ADDRESS, chain: blockchain, }); diff --git a/integration-tests/src/test/set-collect-coins-contract.test.ts b/integration-tests/src/test/set-collect-coins-contract.test.ts index b5b67e7341..9e69a28c71 100644 --- a/integration-tests/src/test/set-collect-coins-contract.test.ts +++ b/integration-tests/src/test/set-collect-coins-contract.test.ts @@ -29,7 +29,7 @@ describe('SetCollectCoinsContract', (): void => { const { api } = ccApi; /* eslint-disable @typescript-eslint/naming-convention */ - const contract = api.createType('PalletCreditcoinOcwTasksCollectCoinsGCreContract', { + const contract = api.createType('PalletCreditcoinOcwTasksCollectCoinsDeployedContract', { address: '0xa3EE21C306A700E682AbCdfe9BaA6A08F3820419', chain: testingData.blockchain, }); diff --git a/pallets/creditcoin/src/benchmarking.rs b/pallets/creditcoin/src/benchmarking.rs index df9bb93d3c..e74d305a7f 100644 --- a/pallets/creditcoin/src/benchmarking.rs +++ b/pallets/creditcoin/src/benchmarking.rs @@ -335,7 +335,7 @@ benchmarks! { set_collect_coins_contract { let root = RawOrigin::Root; - let contract = GCreContract::default(); + let contract = DeployedContract::default(); }: _(root, contract) register_address_v2 { @@ -348,6 +348,11 @@ benchmarks! { let signature = ecdsa_sign(ktypeid, &pkey, &message).expect("ecdsa signature"); let proof = OwnershipProof::EthSign(signature); }: _(RawOrigin::Signed(who), Blockchain::Ethereum, address, proof) + + set_gate_contract { + let root = RawOrigin::Root; + let contract = DeployedContract::default(); + }: _(root, contract) } //impl_benchmark_test_suite!(Creditcoin, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/pallets/creditcoin/src/lib.rs b/pallets/creditcoin/src/lib.rs index b45ef6765f..9b9add3adc 100644 --- a/pallets/creditcoin/src/lib.rs +++ b/pallets/creditcoin/src/lib.rs @@ -35,7 +35,7 @@ pub mod migrations; pub mod ocw; mod types; -use ocw::tasks::collect_coins::GCreContract; +use ocw::tasks::collect_coins::DeployedContract; pub use types::{ loan_terms, Address, AddressId, AskOrder, AskOrderId, AskTerms, BidOrder, BidOrderId, BidTerms, Blockchain, CollectedCoinsId, CollectedCoinsStruct, DealOrder, DealOrderId, Duration, @@ -144,6 +144,7 @@ pub mod pallet { fn remove_authority() -> Weight; fn set_collect_coins_contract() -> Weight; fn register_address_v2() -> Weight; + fn set_gate_contract() -> Weight; } #[pallet::pallet] @@ -229,7 +230,11 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn collect_coins_contract)] - pub type CollectCoinsContract = StorageValue<_, GCreContract, ValueQuery>; + pub type CollectCoinsContract = StorageValue<_, DeployedContract, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn gate_contract)] + pub type GATEConract = StorageValue<_, DeployedContract, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -1323,7 +1328,7 @@ pub mod pallet { #[pallet::weight(::WeightInfo::set_collect_coins_contract())] pub fn set_collect_coins_contract( origin: OriginFor, - contract: GCreContract, + contract: DeployedContract, ) -> DispatchResult { ensure_root(origin)?; CollectCoinsContract::::put(contract); @@ -1401,5 +1406,19 @@ pub mod pallet { }, } } + + /// Set the onchain details for the Gluwa GATE Contract, including its address and the blockchain where it is deployed. + /// This extrinsic expects the caller to have root permissions. + #[transactional] + #[pallet::call_index(23)] + #[pallet::weight(::WeightInfo::set_gate_contract())] + pub fn set_gate_contract( + origin: OriginFor, + contract: DeployedContract, + ) -> DispatchResult { + ensure_root(origin)?; + GATEConract::::put(contract); + Ok(()) + } } } diff --git a/pallets/creditcoin/src/ocw/tasks/collect_coins.rs b/pallets/creditcoin/src/ocw/tasks/collect_coins.rs index fc357c36b4..32bcc506f9 100644 --- a/pallets/creditcoin/src/ocw/tasks/collect_coins.rs +++ b/pallets/creditcoin/src/ocw/tasks/collect_coins.rs @@ -22,25 +22,25 @@ use sp_runtime::SaturatedConversion; use sp_std::prelude::*; #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct GCreContract { +pub struct DeployedContract { pub address: sp_core::H160, pub chain: Blockchain, } -impl GCreContract { +impl DeployedContract { const DEFAULT_CHAIN: Blockchain = Blockchain::Ethereum; } -impl Default for GCreContract { +impl Default for DeployedContract { fn default() -> Self { - let contract_chain: Blockchain = GCreContract::DEFAULT_CHAIN; + let contract_chain: Blockchain = DeployedContract::DEFAULT_CHAIN; let contract_address: H160 = sp_core::H160(hex!("a3EE21C306A700E682AbCdfe9BaA6A08F3820419")); Self { address: contract_address, chain: contract_chain } } } -impl GCreContract { +impl DeployedContract { ///exchange has been deprecated, use burn instead fn burn_vested_cc_abi() -> Function { #[allow(deprecated)] @@ -90,7 +90,7 @@ pub fn validate_collect_coins( return Err(VerificationFailureCause::MissingSender.into()); } - let transfer_fn = GCreContract::burn_vested_cc_abi(); + let transfer_fn = DeployedContract::burn_vested_cc_abi(); ensure!(!transaction.is_input_empty(), VerificationFailureCause::EmptyInput); { @@ -122,7 +122,7 @@ impl Pallet { u_cc: &UnverifiedCollectedCoins, ) -> VerificationResult { log::debug!("verifying OCW Collect Coins"); - let UnverifiedCollectedCoins { to, tx_id, contract: GCreContract { address, chain } } = + let UnverifiedCollectedCoins { to, tx_id, contract: DeployedContract { address, chain } } = u_cc; let rpc_url = &chain.rpc_url()?; let tx = ocw::eth_get_transaction(tx_id, rpc_url)?; @@ -139,9 +139,9 @@ impl Pallet { #[cfg(any(test, feature = "runtime-benchmarks"))] pub(crate) mod testing_constants { - use super::{Blockchain, GCreContract}; + use super::{Blockchain, DeployedContract}; - pub const CHAIN: Blockchain = GCreContract::DEFAULT_CHAIN; + pub const CHAIN: Blockchain = DeployedContract::DEFAULT_CHAIN; } #[cfg(test)] @@ -200,7 +200,7 @@ pub(crate) mod tests { }); pub(crate) static RPC_RESPONSE_AMOUNT: Lazy = Lazy::new(|| { - let transfer_fn = GCreContract::burn_vested_cc_abi(); + let transfer_fn = DeployedContract::burn_vested_cc_abi(); let inputs = transfer_fn.decode_input(&(INPUT.0)[4..]).unwrap(); @@ -282,7 +282,7 @@ pub(crate) mod tests { receipt: EthTransactionReceipt { status: Some(1u64.into()), ..Default::default() }, transaction, eth_tip: (base_height + ETH_CONFIRMATIONS), - contract_address: GCreContract::default().address, + contract_address: DeployedContract::default().address, } } } @@ -1008,7 +1008,7 @@ pub(crate) mod tests { let acct_pubkey = ext.generate_authority(); let _auth = AccountId::from(acct_pubkey.into_account().0); ext.build_and_execute(|| { - let contract = GCreContract { + let contract = DeployedContract { address: sp_core::H160(hex!("aaaaabbbbbcccccdddddeeeeefffff08F3820419")), chain: Blockchain::Rinkeby, }; @@ -1018,7 +1018,7 @@ pub(crate) mod tests { )); let from_storage = Creditcoin::::collect_coins_contract(); assert_eq!(contract, from_storage); - assert_ne!(from_storage, GCreContract::default()); + assert_ne!(from_storage, DeployedContract::default()); let (acc, ..) = generate_address_with_proof("somebody"); @@ -1039,7 +1039,7 @@ pub(crate) mod tests { #[test] fn gcrecontract_value_query_is_default() { - let contract = GCreContract::default(); + let contract = DeployedContract::default(); let ext = ExtBuilder::default(); ext.build_and_execute(|| { let value_query = Creditcoin::::collect_coins_contract(); @@ -1093,7 +1093,7 @@ pub(crate) mod tests { let cc = UnverifiedCollectedCoins { to: addr, tx_id: TX_HASH.hex_to_address(), - contract: GCreContract::default(), + contract: DeployedContract::default(), }; assert_matches!( Creditcoin::::verify_collect_coins_ocw(&cc), @@ -1117,7 +1117,7 @@ pub(crate) mod tests { let cc = UnverifiedCollectedCoins { to: addr, tx_id: TX_HASH.hex_to_address(), - contract: GCreContract::default(), + contract: DeployedContract::default(), }; let id = TaskV2::::to_id(&cc); @@ -1155,7 +1155,7 @@ pub(crate) mod tests { let cc = UnverifiedCollectedCoins { to: addr, tx_id: TX_HASH.hex_to_address(), - contract: GCreContract::default(), + contract: DeployedContract::default(), }; let id = TaskV2::::to_id(&cc); diff --git a/pallets/creditcoin/src/tests.rs b/pallets/creditcoin/src/tests.rs index 3e68bd718b..2835ef78f1 100644 --- a/pallets/creditcoin/src/tests.rs +++ b/pallets/creditcoin/src/tests.rs @@ -5,6 +5,7 @@ use crate::{ non_paying_error, EVMAddress, PublicToAddress, }, mock::{RuntimeOrigin as Origin, *}, + ocw::tasks::collect_coins::DeployedContract, types::{DoubleMapExt, OwnershipProof}, AddressId, AskOrder, AskOrderId, BidOrder, BidOrderId, Blockchain, DealOrder, DealOrderId, DealOrders, Duration, ExternalAddress, ExternalAmount, Guid, Id, LegacySighash, LoanTerms, @@ -3236,3 +3237,47 @@ fn register_address_v2_should_error_with_unsupported_blockchain() { ); }); } + +use hex_literal::hex; + +#[test] +fn set_burn_gate_contract_should_return_default_goerli_contract_when_not_set() { + ExtBuilder::default().build_and_execute(|| { + let contract: DeployedContract = Creditcoin::gate_contract(); + + assert_eq!( + contract.address, + sp_core::H160(hex!("a3EE21C306A700E682AbCdfe9BaA6A08F3820419")) + ); + + assert_eq!(contract.chain, Blockchain::Ethereum); + }); +} + +#[test] +fn set_burn_gate_contract_fails_with_non_root() { + ExtBuilder::default().build_and_execute(|| { + let acct: AccountId = AccountId::new([0; 32]); + let gate_contract = DeployedContract::default(); + + assert_noop!(Creditcoin::set_gate_contract(Origin::signed(acct), gate_contract), BadOrigin); + }); +} + +#[test] +fn set_burn_gate_contract_passes_and_storage_is_updated() { + ExtBuilder::default().build_and_execute(|| { + let fake_address = + sp_core::H160([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + + let gate_contract = + DeployedContract { address: fake_address, chain: Blockchain::Luniverse }; + + assert_ok!(Creditcoin::set_gate_contract(RawOrigin::Root.into(), gate_contract)); + + let stored_contract = Creditcoin::gate_contract(); + + assert_eq!(stored_contract.address, fake_address); + assert_eq!(stored_contract.chain, Blockchain::Luniverse); + }); +} diff --git a/pallets/creditcoin/src/types.rs b/pallets/creditcoin/src/types.rs index 99f6d6465b..9ca005e72c 100644 --- a/pallets/creditcoin/src/types.rs +++ b/pallets/creditcoin/src/types.rs @@ -8,7 +8,7 @@ pub use collect_coins::{ pub use loan_terms::*; pub use transfer::*; -use crate::ocw::tasks::collect_coins::GCreContract; +use crate::ocw::tasks::collect_coins::DeployedContract; use crate::ocw::VerificationFailureCause; use crate::ocw::VerificationResult; use extend::ext; diff --git a/pallets/creditcoin/src/types/collect_coins.rs b/pallets/creditcoin/src/types/collect_coins.rs index 6935700ca6..d96f6af6d9 100644 --- a/pallets/creditcoin/src/types/collect_coins.rs +++ b/pallets/creditcoin/src/types/collect_coins.rs @@ -1,5 +1,5 @@ use crate::types::{ - AddressId, Blockchain, ExternalAddress, ExternalTxId, GCreContract, SystemConfig, + AddressId, Blockchain, DeployedContract, ExternalAddress, ExternalTxId, SystemConfig, }; use frame_support::RuntimeDebug; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -16,7 +16,7 @@ pub struct CollectedCoins { pub struct UnverifiedCollectedCoins { pub to: ExternalAddress, pub tx_id: ExternalTxId, - pub contract: GCreContract, + pub contract: DeployedContract, } impl UnverifiedCollectedCoins { @@ -24,7 +24,7 @@ impl UnverifiedCollectedCoins { where T: Config, { - let Self { to, tx_id, contract: GCreContract { chain, .. } } = self; + let Self { to, tx_id, contract: DeployedContract { chain, .. } } = self; let to = crate::AddressId::new::(&chain, to.as_slice()); CollectedCoins { amount, to, tx_id } } diff --git a/pallets/creditcoin/src/weights.rs b/pallets/creditcoin/src/weights.rs index 37171ca1ed..34caf6cc96 100644 --- a/pallets/creditcoin/src/weights.rs +++ b/pallets/creditcoin/src/weights.rs @@ -451,4 +451,8 @@ impl crate::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + + fn set_gate_contract() -> Weight { + Weight::from_parts(0,0) + } }