From bd26cf05a3016ffeecabfbdce9b3c2356df2e355 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Sat, 20 Jul 2024 14:43:35 +0200 Subject: [PATCH 01/18] refactor: remove old api code (#112) --- runtime/devnet/src/extensions.rs | 706 +----------------------------- runtime/devnet/src/lib.rs | 43 +- runtime/testnet/src/extensions.rs | 551 +---------------------- runtime/testnet/src/lib.rs | 43 +- 4 files changed, 20 insertions(+), 1323 deletions(-) diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 7e2a53c0..d2d11598 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -1,30 +1,17 @@ -use cumulus_pallet_parachain_system::RelaychainDataProvider; use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; -use pop_primitives::{ - cross_chain::CrossChainMessage, - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - CollectionId, ItemId, -}; +use pop_primitives::storage_keys::RuntimeStateKeys; use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, -}; -use sp_std::{boxed::Box, vec::Vec}; -use xcm::{ - latest::{prelude::*, OriginKind::SovereignAccount}, - VersionedXcm, -}; +use sp_runtime::{traits::Dispatchable, DispatchError}; +use sp_std::vec::Vec; -use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin, UNIT}; +use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; const LOG_TARGET: &str = "pop-api::extension"; @@ -36,9 +23,6 @@ pub struct PopApiExtension; impl ChainExtension for PopApiExtension where T: pallet_contracts::Config - + pallet_xcm::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config + frame_system::Config< RuntimeOrigin = RuntimeOrigin, AccountId = AccountId, @@ -49,7 +33,6 @@ where fn call(&mut self, env: Environment) -> Result where E: Ext, - T::AccountId: UncheckedFrom + AsRef<[u8]>, { log::debug!(target:LOG_TARGET, " extension called "); match v0::FuncId::try_from(env.func_id())? { @@ -70,10 +53,6 @@ where read_state::(env)?; Ok(RetVal::Converging(0)) }, - v0::FuncId::SendXcm => { - send_xcm::(env)?; - Ok(RetVal::Converging(0)) - }, } } } @@ -83,7 +62,6 @@ pub mod v0 { pub enum FuncId { Dispatch, ReadState, - SendXcm, } } @@ -94,7 +72,6 @@ impl TryFrom for v0::FuncId { let id = match func_id { 0x0 => Self::Dispatch, 0x1 => Self::ReadState, - 0x2 => Self::SendXcm, _ => { log::error!("called an unregistered `func_id`: {:}", func_id); return Err(DispatchError::Other("unimplemented func_id")); @@ -112,8 +89,6 @@ fn dispatch_call( log_prefix: &str, ) -> Result<(), DispatchError> where - T: frame_system::Config, - RuntimeOrigin: From>, E: Ext, { let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; @@ -168,8 +143,7 @@ where fn dispatch(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + frame_system::Config, + T: pallet_contracts::Config, RuntimeOrigin: From>, E: Ext, { @@ -191,10 +165,7 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config, + T: pallet_contracts::Config, E: Ext, { const LOG_PREFIX: &str = " read_state |"; @@ -213,11 +184,8 @@ where let key: RuntimeStateKeys = env.read_as()?; let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), - RuntimeStateKeys::ParachainSystem(key) => { - read_parachain_system_state::(key, &mut env) - }, - }? + _ => Vec::::default(), + } .encode(); log::trace!( @@ -229,661 +197,3 @@ where DispatchError::Other("unable to write results to contract memory") }) } - -fn read_parachain_system_state( - key: ParachainSystemKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, - E: Ext, -{ - match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(RelaychainDataProvider::::current_block_number().encode()) - }, - } -} - -fn read_nfts_state( - key: NftsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + pallet_nfts::Config, - E: Ext, -{ - match key { - NftsKeys::Collection(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Collection::::get(collection).encode()) - }, - NftsKeys::CollectionOwner(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) - }, - NftsKeys::Item(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Item::::get(collection, item).encode()) - }, - NftsKeys::Owner(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) - }, - NftsKeys::Attribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) - }, - // NftsKeys::CustomAttribute(account, collection, item, key) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) - // .encode()) - // }, - NftsKeys::SystemAttribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) - .encode()) - }, - NftsKeys::CollectionAttribute(collection, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) - }, - } -} - -fn send_xcm(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config - + frame_system::Config< - RuntimeOrigin = RuntimeOrigin, - AccountId = AccountId, - RuntimeCall = RuntimeCall, - >, - E: Ext, -{ - const LOG_PREFIX: &str = " send_xcm |"; - - let mut env = env.buf_in_buf_out(); - let len = env.in_len(); - - let _ = charge_overhead_weight::(&mut env, len, LOG_PREFIX)?; - - // read the input as CrossChainMessage - let xc_call: CrossChainMessage = env.read_as::()?; - - // Determine the call to dispatch - let (dest, message) = match xc_call { - CrossChainMessage::Relay(message) => { - let dest = Location::parent().into_versioned(); - let assets: Asset = (Here, 10 * UNIT).into(); - let beneficiary: Location = - AccountId32 { id: (env.ext().address().clone()).into(), network: None }.into(); - let message = Xcm::builder() - .withdraw_asset(assets.clone().into()) - .buy_execution(assets.clone(), Unlimited) - .transact( - SovereignAccount, - Weight::from_parts(250_000_000, 10_000), - message.encode().into(), - ) - .refund_surplus() - .deposit_asset(assets.into(), beneficiary) - .build(); - (dest, message) - }, - }; - - // TODO: revisit to replace with signed contract origin - let origin: RuntimeOrigin = RawOrigin::Root.into(); - - // Generate runtime call to dispatch - let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::send { - dest: Box::new(dest), - message: Box::new(VersionedXcm::V4(message)), - }); - - dispatch_call::(&mut env, call, origin, LOG_PREFIX) -} - -#[cfg(test)] -mod tests { - pub use super::*; - pub use crate::*; - use enumflags2::BitFlags; - pub use pallet_contracts::Code; - use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; - use parachains_common::CollectionId; - pub use sp_runtime::{traits::Hash, AccountId32}; - - const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - - const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); - const BOB: AccountId32 = AccountId32::new([2_u8; 32]); - const INITIAL_AMOUNT: u128 = 100_000 * UNIT; - const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INITIAL_AMOUNT), (BOB, INITIAL_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - - fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> - where - T: frame_system::Config, - { - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) - } - - fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() - } - - // NFT helper functions - fn collection_config_from_disabled_settings( - settings: BitFlags, - ) -> CollectionConfig { - CollectionConfig { - settings: CollectionSettings::from_disabled(settings), - max_supply: None, - mint_settings: MintSettings::default(), - } - } - - fn default_collection_config() -> CollectionConfig { - collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) - } - - #[test] - #[ignore] - fn dispatch_balance_transfer_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("transfer_through_runtime"); - let value_to_send: u128 = 10 * UNIT; - let params = [function, BOB.encode(), value_to_send.encode()].concat(); - - let bob_balance_before = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before, INITIAL_AMOUNT); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before + value_to_send, bob_balance_after); - }); - } - - // Create a test for tesing create_nft_collection - #[test] - #[ignore] - fn dispatch_nfts_create_nft_collection() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/nfts/target/ink/pop_api_nft_example.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("create_nft_collection"); - - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check that the nft collection was created - assert_eq!(Nfts::collection_owner(0), Some(addr.clone().into())); - - // test reading the collection - let function = function_selector("read_collection"); - - let params = [function, 0.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // assert that the collection was read successfully - assert_eq!(result.result.clone().unwrap().data, vec![1, 1]); - }); - } - - #[test] - #[ignore] - fn dispatch_nfts_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - // create nft collection with contract as owner - assert_eq!( - Nfts::force_create( - RuntimeOrigin::root(), - addr.clone().into(), - default_collection_config() - ), - Ok(()) - ); - - assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); - // assert that the item does not exist yet - assert_eq!(Nfts::owner(collection_id, item_id), None); - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); - }); - } - - #[test] - #[ignore] - fn nfts_mint_surfaces_error() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert with expected error - let result = result.result.unwrap(); - assert!(result.did_revert()); - }); - } - - #[test] - #[ignore] - fn reading_last_relay_chain_block_number_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", - ) - .unwrap(); - - let init_value = 100; - - let contract = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); - - let addr = contract.account_id; - - let function = function_selector("read_relay_block_number"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::UnsafeCollect, - pallet_contracts::Determinism::Relaxed, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn place_spot_order_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("place_spot_order"); - - let max_amount = 1 * UNIT; - let para_id = 2000; - - let params = [function, max_amount.encode(), para_id.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn allow_call_filter_blocks_call() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("get_filtered"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("filtered result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } -} diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index ffca8a12..738f7a0d 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -252,46 +252,9 @@ impl Contains for FilteredCalls { /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API pub struct AllowedApiCalls; -impl Contains for crate::AllowedApiCalls { - fn contains(c: &RuntimeCall) -> bool { - use pallet_nfts::Call as NftsCall; - matches!( - c, - RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) - ) +impl Contains for AllowedApiCalls { + fn contains(_c: &RuntimeCall) -> bool { + false } } diff --git a/runtime/testnet/src/extensions.rs b/runtime/testnet/src/extensions.rs index d6f2d656..d2d11598 100644 --- a/runtime/testnet/src/extensions.rs +++ b/runtime/testnet/src/extensions.rs @@ -1,22 +1,14 @@ -use cumulus_pallet_parachain_system::RelaychainDataProvider; use frame_support::traits::{Contains, OriginTrait}; use frame_support::{ dispatch::{GetDispatchInfo, RawOrigin}, pallet_prelude::*, - traits::nonfungibles_v2::Inspect, }; use pallet_contracts::chain_extension::{ BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, }; -use pop_primitives::{ - storage_keys::{NftsKeys, ParachainSystemKeys, RuntimeStateKeys}, - CollectionId, ItemId, -}; +use pop_primitives::storage_keys::RuntimeStateKeys; use sp_core::crypto::UncheckedFrom; -use sp_runtime::{ - traits::{BlockNumberProvider, Dispatchable}, - DispatchError, -}; +use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_std::vec::Vec; use crate::{AccountId, AllowedApiCalls, RuntimeCall, RuntimeOrigin}; @@ -31,9 +23,6 @@ pub struct PopApiExtension; impl ChainExtension for PopApiExtension where T: pallet_contracts::Config - + pallet_xcm::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config + frame_system::Config< RuntimeOrigin = RuntimeOrigin, AccountId = AccountId, @@ -44,7 +33,6 @@ where fn call(&mut self, env: Environment) -> Result where E: Ext, - T::AccountId: UncheckedFrom + AsRef<[u8]>, { log::debug!(target:LOG_TARGET, " extension called "); match v0::FuncId::try_from(env.func_id())? { @@ -101,8 +89,6 @@ fn dispatch_call( log_prefix: &str, ) -> Result<(), DispatchError> where - T: frame_system::Config, - RuntimeOrigin: From>, E: Ext, { let charged_dispatch_weight = env.charge_weight(call.get_dispatch_info().weight)?; @@ -157,8 +143,7 @@ where fn dispatch(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + frame_system::Config, + T: pallet_contracts::Config, RuntimeOrigin: From>, E: Ext, { @@ -180,10 +165,7 @@ where fn read_state(env: Environment) -> Result<(), DispatchError> where - T: pallet_contracts::Config - + pallet_nfts::Config - + cumulus_pallet_parachain_system::Config - + frame_system::Config, + T: pallet_contracts::Config, E: Ext, { const LOG_PREFIX: &str = " read_state |"; @@ -202,11 +184,8 @@ where let key: RuntimeStateKeys = env.read_as()?; let result = match key { - RuntimeStateKeys::Nfts(key) => read_nfts_state::(key, &mut env), - RuntimeStateKeys::ParachainSystem(key) => { - read_parachain_system_state::(key, &mut env) - }, - }? + _ => Vec::::default(), + } .encode(); log::trace!( @@ -218,521 +197,3 @@ where DispatchError::Other("unable to write results to contract memory") }) } - -fn read_parachain_system_state( - key: ParachainSystemKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, - E: Ext, -{ - match key { - ParachainSystemKeys::LastRelayChainBlockNumber => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(RelaychainDataProvider::::current_block_number().encode()) - }, - } -} - -fn read_nfts_state( - key: NftsKeys, - env: &mut Environment, -) -> Result, DispatchError> -where - T: pallet_contracts::Config + pallet_nfts::Config, - E: Ext, -{ - match key { - NftsKeys::Collection(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Collection::::get(collection).encode()) - }, - NftsKeys::CollectionOwner(collection) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_owner(collection).encode()) - }, - NftsKeys::Item(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Item::::get(collection, item).encode()) - }, - NftsKeys::Owner(collection, item) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::owner(collection, item).encode()) - }, - NftsKeys::Attribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::attribute(&collection, &item, &key).encode()) - }, - // NftsKeys::CustomAttribute(account, collection, item, key) => { - // env.charge_weight(T::DbWeight::get().reads(1_u64))?; - // Ok(pallet_nfts::Pallet::::custom_attribute(&account, &collection, &item, &key) - // .encode()) - // }, - NftsKeys::SystemAttribute(collection, item, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::system_attribute(&collection, item.as_ref(), &key) - .encode()) - }, - NftsKeys::CollectionAttribute(collection, key) => { - env.charge_weight(T::DbWeight::get().reads(1_u64))?; - Ok(pallet_nfts::Pallet::::collection_attribute(&collection, &key).encode()) - }, - } -} - -#[cfg(test)] -mod tests { - pub use super::*; - pub use crate::*; - use enumflags2::BitFlags; - pub use pallet_contracts::Code; - use pallet_nfts::{CollectionConfig, CollectionSetting, CollectionSettings, MintSettings}; - use parachains_common::CollectionId; - pub use sp_runtime::{traits::Hash, AccountId32}; - - const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; - - const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); - const BOB: AccountId32 = AccountId32::new([2_u8; 32]); - const INITIAL_AMOUNT: u128 = 100_000 * UNIT; - const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INITIAL_AMOUNT), (BOB, INITIAL_AMOUNT)], - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - - fn load_wasm_module(path: &str) -> std::io::Result<(Vec, ::Output)> - where - T: frame_system::Config, - { - let wasm_binary = std::fs::read(path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) - } - - fn function_selector(name: &str) -> Vec { - let hash = sp_io::hashing::blake2_256(name.as_bytes()); - [hash[0..4].to_vec()].concat() - } - - // NFT helper functions - fn collection_config_from_disabled_settings( - settings: BitFlags, - ) -> CollectionConfig { - CollectionConfig { - settings: CollectionSettings::from_disabled(settings), - max_supply: None, - mint_settings: MintSettings::default(), - } - } - - fn default_collection_config() -> CollectionConfig { - collection_config_from_disabled_settings(CollectionSetting::DepositRequired.into()) - } - - #[test] - #[ignore] - fn dispatch_balance_transfer_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/balance-transfer/target/ink/balance_transfer.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("transfer_through_runtime"); - let value_to_send: u128 = 10 * UNIT; - let params = [function, BOB.encode(), value_to_send.encode()].concat(); - - let bob_balance_before = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before, INITIAL_AMOUNT); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - let bob_balance_after = Balances::free_balance(&BOB); - assert_eq!(bob_balance_before + value_to_send, bob_balance_after); - }); - } - - #[test] - #[ignore] - fn dispatch_nfts_mint_from_contract_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - // create nft collection with contract as owner - assert_eq!( - Nfts::force_create( - RuntimeOrigin::root(), - addr.clone().into(), - default_collection_config() - ), - Ok(()) - ); - - assert_eq!(Nfts::collection_owner(collection_id), Some(addr.clone().into())); - // assert that the item does not exist yet - assert_eq!(Nfts::owner(collection_id, item_id), None); - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - - assert_eq!(Nfts::owner(collection_id, item_id), Some(BOB.into())); - }); - } - - #[test] - #[ignore] - fn nfts_mint_surfaces_error() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = - load_wasm_module::("../../pop-api/examples/nfts/target/ink/nfts.wasm") - .unwrap(); - - let init_value = 100; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let collection_id: u32 = 0; - let item_id: u32 = 1; - - let function = function_selector("mint_through_runtime"); - - let params = - [function, collection_id.encode(), item_id.encode(), BOB.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert with expected error - let result = result.result.unwrap(); - assert!(result.did_revert()); - }); - } - - #[test] - #[ignore] - fn reading_last_relay_chain_block_number_works() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/read-runtime-state/target/ink/read_relay_blocknumber.wasm", - ) - .unwrap(); - - let init_value = 100; - - let contract = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!contract.result.did_revert(), "deploying contract reverted {:?}", contract); - - let addr = contract.account_id; - - let function = function_selector("read_relay_block_number"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::UnsafeCollect, - pallet_contracts::Determinism::Relaxed, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } - - #[test] - #[ignore] - fn place_spot_order_from_contract_fails() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../pop-api/examples/place-spot-order/target/ink/spot_order.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("place_spot_order"); - - let max_amount = 1 * UNIT; - let para_id = 2000; - - let params = [function, max_amount.encode(), para_id.encode()].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("result: {:?}", result); - } - - // check for revert - assert!( - result.result.is_err(), - "Contract execution should have failed - unimplemented runtime call!" - ); - }); - } - - #[test] - #[ignore] - fn allow_call_filter_blocks_call() { - new_test_ext().execute_with(|| { - let _ = env_logger::try_init(); - - let (wasm_binary, _) = load_wasm_module::( - "../../tests/contracts/filtered-call/target/ink/pop_api_filtered_call.wasm", - ) - .unwrap(); - - let init_value = 100 * UNIT; - - let result = Contracts::bare_instantiate( - ALICE, - init_value, - GAS_LIMIT, - None, - Code::Upload(wasm_binary), - function_selector("new"), - vec![], - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - ) - .result - .unwrap(); - - assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); - - let addr = result.account_id; - - let function = function_selector("get_filtered"); - let params = [function].concat(); - - let result = Contracts::bare_call( - ALICE, - addr.clone(), - 0, - Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), - None, - params, - DEBUG_OUTPUT, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { - log::debug!( - "Contract debug buffer - {:?}", - String::from_utf8(result.debug_message.clone()) - ); - log::debug!("filtered result: {:?}", result); - } - - // check for revert - assert!(!result.result.unwrap().did_revert(), "Contract reverted!"); - }); - } -} diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 37f378f7..5573ef18 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -251,46 +251,9 @@ impl Contains for FilteredCalls { /// A type to identify allowed calls to the Runtime from contracts. Used by Pop API pub struct AllowedApiCalls; -impl Contains for crate::AllowedApiCalls { - fn contains(c: &RuntimeCall) -> bool { - use pallet_nfts::Call as NftsCall; - matches!( - c, - RuntimeCall::Balances(BalancesCall::transfer_keep_alive { .. }) - | RuntimeCall::Nfts( - NftsCall::create { .. } - | NftsCall::destroy { .. } - | NftsCall::mint { .. } | NftsCall::burn { .. } - | NftsCall::transfer { .. } - | NftsCall::redeposit { .. } - | NftsCall::lock_item_transfer { .. } - | NftsCall::unlock_item_transfer { .. } - | NftsCall::lock_collection { .. } - | NftsCall::transfer_ownership { .. } - | NftsCall::set_team { .. } - | NftsCall::approve_transfer { .. } - | NftsCall::cancel_approval { .. } - | NftsCall::clear_all_transfer_approvals { .. } - | NftsCall::lock_item_properties { .. } - | NftsCall::set_attribute { .. } - | NftsCall::clear_attribute { .. } - | NftsCall::approve_item_attributes { .. } - | NftsCall::cancel_item_attributes_approval { .. } - | NftsCall::set_metadata { .. } - | NftsCall::clear_metadata { .. } - | NftsCall::set_collection_metadata { .. } - | NftsCall::clear_collection_metadata { .. } - | NftsCall::set_accept_ownership { .. } - | NftsCall::set_collection_max_supply { .. } - | NftsCall::update_mint_settings { .. } - | NftsCall::set_price { .. } - | NftsCall::buy_item { .. } - | NftsCall::pay_tips { .. } - | NftsCall::create_swap { .. } - | NftsCall::cancel_swap { .. } - | NftsCall::claim_swap { .. } - ) - ) +impl Contains for AllowedApiCalls { + fn contains(_c: &RuntimeCall) -> bool { + false } } From 5c25ab5fb26d09fdc5facd8ea97296cc5e7f1ea6 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Tue, 23 Jul 2024 23:36:16 +0700 Subject: [PATCH 02/18] refractor: build chain extension method --- pop-api/src/lib.rs | 1 + pop-api/src/utils.rs | 10 ++++++++++ pop-api/src/v0/assets/mod.rs | 25 +++++++++++++------------ 3 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 pop-api/src/utils.rs diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 86621c51..918e100c 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -14,6 +14,7 @@ pub use v0::cross_chain; pub use v0::nfts; pub mod primitives; +pub mod utils; pub mod v0; /// A result type used by the API, with the `StatusCode` as the error type. diff --git a/pop-api/src/utils.rs b/pop-api/src/utils.rs new file mode 100644 index 00000000..59a982f6 --- /dev/null +++ b/pop-api/src/utils.rs @@ -0,0 +1,10 @@ +use ink::env::chain_extension::ChainExtensionMethod; + +pub(crate) fn build_extension_method( + version: u8, + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) +} diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 00021fc0..41c1fb6c 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,8 +1,9 @@ -use ink::{env::chain_extension::ChainExtensionMethod, prelude::vec::Vec, scale::Decode}; +use ink::{prelude::vec::Vec, scale::Decode}; use crate::{ constants::{ASSETS, DECODING_FAILED, DISPATCH, READ_STATE}, primitives::{AccountId, AssetId, Balance}, + utils::build_extension_method, v0::V0, Result, StatusCode, }; @@ -91,13 +92,13 @@ const TRANSFER_APPROVED: u8 = 25; /// Move some assets from the sender account to another, keeping the sender account alive. #[inline] pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([ + build_extension_method( V0, DISPATCH, ASSETS, // E.D. is always respected with transferring tokens via the API. TRANSFER_KEEP_ALIVE, - ])) + ) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -122,7 +123,7 @@ pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> R /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, APPROVE_TRANSFER])) + build_extension_method(V0, DISPATCH, ASSETS, APPROVE_TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -132,7 +133,7 @@ pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Re /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, CANCEL_APPROVAL])) + build_extension_method(V0, DISPATCH, ASSETS, CANCEL_APPROVAL) .input::<(AssetId, AccountId)>() .output::, true>() .handle_error_code::() @@ -148,7 +149,7 @@ pub fn transfer_approved( to: AccountId, amount: Balance, ) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, ASSETS, TRANSFER_APPROVED])) + build_extension_method(V0, DISPATCH, ASSETS, TRANSFER_APPROVED) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -172,7 +173,7 @@ const TOKEN_DECIMALS: u8 = 5; #[inline] pub fn total_supply(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOTAL_SUPPLY])) + build_extension_method(V0, READ_STATE, ASSETS, TOTAL_SUPPLY) .input::() .output::>, true>() .handle_error_code::() @@ -182,7 +183,7 @@ pub fn total_supply(id: AssetId) -> Result { #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, BALANCE_OF])) + build_extension_method(V0, READ_STATE, ASSETS, BALANCE_OF) .input::<(AssetId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -192,7 +193,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, ALLOWANCE])) + build_extension_method(V0, READ_STATE, ASSETS, ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -202,7 +203,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_NAME])) + build_extension_method(V0, READ_STATE, ASSETS, TOKEN_NAME) .input::() .output::>, true>() .handle_error_code::() @@ -212,7 +213,7 @@ pub fn token_name(id: AssetId) -> Result> { // #[inline] pub fn token_symbol(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_SYMBOL])) + build_extension_method(V0, READ_STATE, ASSETS, TOKEN_SYMBOL) .input::() .output::>, true>() .handle_error_code::() @@ -222,7 +223,7 @@ pub fn token_symbol(id: AssetId) -> Result> { #[inline] pub fn token_decimals(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, ASSETS, TOKEN_DECIMALS])) + build_extension_method(V0, READ_STATE, ASSETS, TOKEN_DECIMALS) .input::() .output::>, true>() .handle_error_code::() From 438afd7bada64c7176ea7b60c9ae2e1f979a84a0 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:33:39 +0700 Subject: [PATCH 03/18] refractor: simplify the methods --- pop-api/src/lib.rs | 13 +++++++++++-- pop-api/src/utils.rs | 10 ---------- pop-api/src/v0/assets/mod.rs | 27 ++++++++++++--------------- pop-api/src/v0/mod.rs | 27 ++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 28 deletions(-) delete mode 100644 pop-api/src/utils.rs diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 918e100c..1aa2c985 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use ink::env::chain_extension::FromStatusCode; +use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; use constants::DECODING_FAILED; @@ -14,7 +14,6 @@ pub use v0::cross_chain; pub use v0::nfts; pub mod primitives; -pub mod utils; pub mod v0; /// A result type used by the API, with the `StatusCode` as the error type. @@ -34,6 +33,16 @@ mod constants { pub(crate) const BALANCES: u8 = 10; } +/// Helper method to build `ChainExtensionMethod`` +pub fn build_extension_method( + version: u8, + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) +} + /// Represents a status code returned by the runtime. /// /// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed diff --git a/pop-api/src/utils.rs b/pop-api/src/utils.rs deleted file mode 100644 index 59a982f6..00000000 --- a/pop-api/src/utils.rs +++ /dev/null @@ -1,10 +0,0 @@ -use ink::env::chain_extension::ChainExtensionMethod; - -pub(crate) fn build_extension_method( - version: u8, - function: u8, - module: u8, - dispatchable: u8, -) -> ChainExtensionMethod<(), (), (), false> { - ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) -} diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 41c1fb6c..ba811728 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -1,10 +1,9 @@ use ink::{prelude::vec::Vec, scale::Decode}; use crate::{ - constants::{ASSETS, DECODING_FAILED, DISPATCH, READ_STATE}, + constants::{ASSETS, DECODING_FAILED}, primitives::{AccountId, AssetId, Balance}, - utils::build_extension_method, - v0::V0, + v0::{build_dispatch, build_read_state}, Result, StatusCode, }; @@ -92,9 +91,7 @@ const TRANSFER_APPROVED: u8 = 25; /// Move some assets from the sender account to another, keeping the sender account alive. #[inline] pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { - build_extension_method( - V0, - DISPATCH, + build_dispatch( ASSETS, // E.D. is always respected with transferring tokens via the API. TRANSFER_KEEP_ALIVE, @@ -123,7 +120,7 @@ pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> R /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - build_extension_method(V0, DISPATCH, ASSETS, APPROVE_TRANSFER) + build_dispatch(ASSETS, APPROVE_TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -133,7 +130,7 @@ pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Re /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - build_extension_method(V0, DISPATCH, ASSETS, CANCEL_APPROVAL) + build_dispatch(ASSETS, CANCEL_APPROVAL) .input::<(AssetId, AccountId)>() .output::, true>() .handle_error_code::() @@ -149,7 +146,7 @@ pub fn transfer_approved( to: AccountId, amount: Balance, ) -> Result<()> { - build_extension_method(V0, DISPATCH, ASSETS, TRANSFER_APPROVED) + build_dispatch(ASSETS, TRANSFER_APPROVED) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -173,7 +170,7 @@ const TOKEN_DECIMALS: u8 = 5; #[inline] pub fn total_supply(id: AssetId) -> Result { - build_extension_method(V0, READ_STATE, ASSETS, TOTAL_SUPPLY) + build_read_state(ASSETS, TOTAL_SUPPLY) .input::() .output::>, true>() .handle_error_code::() @@ -183,7 +180,7 @@ pub fn total_supply(id: AssetId) -> Result { #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - build_extension_method(V0, READ_STATE, ASSETS, BALANCE_OF) + build_read_state(ASSETS, BALANCE_OF) .input::<(AssetId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -193,7 +190,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - build_extension_method(V0, READ_STATE, ASSETS, ALLOWANCE) + build_read_state(ASSETS, ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -203,7 +200,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result> { - build_extension_method(V0, READ_STATE, ASSETS, TOKEN_NAME) + build_read_state(ASSETS, TOKEN_NAME) .input::() .output::>, true>() .handle_error_code::() @@ -213,7 +210,7 @@ pub fn token_name(id: AssetId) -> Result> { // #[inline] pub fn token_symbol(id: AssetId) -> Result> { - build_extension_method(V0, READ_STATE, ASSETS, TOKEN_SYMBOL) + build_read_state(ASSETS, TOKEN_SYMBOL) .input::() .output::>, true>() .handle_error_code::() @@ -223,7 +220,7 @@ pub fn token_symbol(id: AssetId) -> Result> { #[inline] pub fn token_decimals(id: AssetId) -> Result { - build_extension_method(V0, READ_STATE, ASSETS, TOKEN_DECIMALS) + build_read_state(ASSETS, TOKEN_DECIMALS) .input::() .output::>, true>() .handle_error_code::() diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index f7dab6b4..2fcca56a 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,4 +1,10 @@ -use crate::{primitives::error::Error, StatusCode}; +use crate::{ + build_extension_method, + constants::{DISPATCH, READ_STATE}, + primitives::error::Error, + StatusCode, +}; +use ink::env::chain_extension::ChainExtensionMethod; #[cfg(feature = "assets")] pub mod assets; @@ -16,3 +22,22 @@ impl From for Error { value.0.into() } } + +/// Helper method to build `ChainExtensionMethod`` +pub fn build_extension_method_v0( + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method(V0, function, module, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` +pub fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(DISPATCH, module, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` +pub fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(READ_STATE, module, dispatchable) +} From eb1f7cd0b0c9f356f2527f037fe646899c7cb413 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:48:34 +0700 Subject: [PATCH 04/18] refractor --- pop-api/src/lib.rs | 7 +++++- pop-api/src/v0/assets/mod.rs | 46 ++++++++++++++++++++++-------------- pop-api/src/v0/mod.rs | 18 ++++++++++---- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 1aa2c985..07bc80f8 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -34,7 +34,12 @@ mod constants { } /// Helper method to build `ChainExtensionMethod`` -pub fn build_extension_method( +/// +/// - `version`: The version of the chain extension +/// - `function`: The ID of the function +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_extension_method( version: u8, function: u8, module: u8, diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index ba811728..bdb52eac 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -3,7 +3,6 @@ use ink::{prelude::vec::Vec, scale::Decode}; use crate::{ constants::{ASSETS, DECODING_FAILED}, primitives::{AccountId, AssetId, Balance}, - v0::{build_dispatch, build_read_state}, Result, StatusCode, }; @@ -33,6 +32,20 @@ const CANCEL_APPROVAL: u8 = 23; /// - transfer_approved const TRANSFER_APPROVED: u8 = 25; +/// Helper method to build a dispatch call `ChainExtensionMethod` for `ASSET` module +/// +/// - `dispatchable`: The index of the dispatchable functions in `ASSET` module +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_dispatch(ASSETS, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` for `ASSET` module +/// +/// - `dispatchable`: The index of the module dispatchable functions +fn build_read_state(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_read_state(ASSETS, dispatchable) +} + /// Issue a new class of fungible assets from a public origin. // pub(crate) fn create( // id: AssetId, @@ -91,15 +104,12 @@ const TRANSFER_APPROVED: u8 = 25; /// Move some assets from the sender account to another, keeping the sender account alive. #[inline] pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { - build_dispatch( - ASSETS, - // E.D. is always respected with transferring tokens via the API. - TRANSFER_KEEP_ALIVE, - ) - .input::<(AssetId, AccountId, Balance)>() - .output::, true>() - .handle_error_code::() - .call(&(id, target, amount)) + // E.D. is always respected with transferring tokens via the API. + build_dispatch(TRANSFER_KEEP_ALIVE) + .input::<(AssetId, AccountId, Balance)>() + .output::, true>() + .handle_error_code::() + .call(&(id, target, amount)) } // /// Set the metadata for an asset. @@ -120,7 +130,7 @@ pub fn transfer_keep_alive(id: AssetId, target: AccountId, amount: Balance) -> R /// Approve an amount of asset for transfer by a delegated third-party account. #[inline] pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Result<()> { - build_dispatch(ASSETS, APPROVE_TRANSFER) + build_dispatch(APPROVE_TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -130,7 +140,7 @@ pub fn approve_transfer(id: AssetId, delegate: AccountId, amount: Balance) -> Re /// Cancel all of some asset approved for delegated transfer by a third-party account. #[inline] pub fn cancel_approval(id: AssetId, delegate: AccountId) -> Result<()> { - build_dispatch(ASSETS, CANCEL_APPROVAL) + build_dispatch(CANCEL_APPROVAL) .input::<(AssetId, AccountId)>() .output::, true>() .handle_error_code::() @@ -146,7 +156,7 @@ pub fn transfer_approved( to: AccountId, amount: Balance, ) -> Result<()> { - build_dispatch(ASSETS, TRANSFER_APPROVED) + build_dispatch(TRANSFER_APPROVED) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -170,7 +180,7 @@ const TOKEN_DECIMALS: u8 = 5; #[inline] pub fn total_supply(id: AssetId) -> Result { - build_read_state(ASSETS, TOTAL_SUPPLY) + build_read_state(TOTAL_SUPPLY) .input::() .output::>, true>() .handle_error_code::() @@ -190,7 +200,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - build_read_state(ASSETS, ALLOWANCE) + build_read_state(ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -200,7 +210,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result> { - build_read_state(ASSETS, TOKEN_NAME) + build_read_state(TOKEN_NAME) .input::() .output::>, true>() .handle_error_code::() @@ -210,7 +220,7 @@ pub fn token_name(id: AssetId) -> Result> { // #[inline] pub fn token_symbol(id: AssetId) -> Result> { - build_read_state(ASSETS, TOKEN_SYMBOL) + build_read_state(TOKEN_SYMBOL) .input::() .output::>, true>() .handle_error_code::() @@ -220,7 +230,7 @@ pub fn token_symbol(id: AssetId) -> Result> { #[inline] pub fn token_decimals(id: AssetId) -> Result { - build_read_state(ASSETS, TOKEN_DECIMALS) + build_read_state(TOKEN_DECIMALS) .input::() .output::>, true>() .handle_error_code::() diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 2fcca56a..834e6454 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -23,8 +23,12 @@ impl From for Error { } } -/// Helper method to build `ChainExtensionMethod`` -pub fn build_extension_method_v0( +/// Helper method to build `ChainExtensionMethod` for version `v0` +/// +/// - `function`: The ID of the function +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_extension_method_v0( function: u8, module: u8, dispatchable: u8, @@ -33,11 +37,17 @@ pub fn build_extension_method_v0( } /// Helper method to build a dispatch call `ChainExtensionMethod` -pub fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { +/// +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` -pub fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { +/// +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(READ_STATE, module, dispatchable) } From 8a4e67565ac5eb6ce7bad5a8aeae5d9bd53df0f0 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 18:50:52 +0700 Subject: [PATCH 05/18] hotfix: build_state_query parameter name --- pop-api/src/v0/assets/mod.rs | 6 +++--- pop-api/src/v0/mod.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index bdb52eac..27c3960f 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -41,9 +41,9 @@ fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { /// Helper method to build a dispatch call `ChainExtensionMethod` for `ASSET` module /// -/// - `dispatchable`: The index of the module dispatchable functions -fn build_read_state(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { - crate::v0::build_read_state(ASSETS, dispatchable) +/// - `state_query`: The index of the runtime state query +fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_read_state(ASSETS, state_query) } /// Issue a new class of fungible assets from a public origin. diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 834e6454..20369154 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -47,7 +47,7 @@ fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), /// Helper method to build a dispatch call `ChainExtensionMethod` /// /// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions -fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(READ_STATE, module, dispatchable) +/// - `state_query`: The index of the runtime state query +fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(READ_STATE, module, state_query) } From adf2eeb9f9524f9a72ba391f34863ec7135800d7 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:27:24 +0800 Subject: [PATCH 06/18] update comment --- pop-api/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 07bc80f8..33a773a1 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -33,12 +33,13 @@ mod constants { pub(crate) const BALANCES: u8 = 10; } -/// Helper method to build `ChainExtensionMethod`` +/// Helper method to build `ChainExtensionMethod`. /// -/// - `version`: The version of the chain extension -/// - `function`: The ID of the function -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'version': The version of the chain extension +/// - 'function': The ID of the function +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_extension_method( version: u8, function: u8, From 69b7f5b9988b1b38f4f7235b177198caeee53b0b Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:28:57 +0800 Subject: [PATCH 07/18] update comment --- pop-api/src/v0/assets/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pop-api/src/v0/assets/mod.rs b/pop-api/src/v0/assets/mod.rs index 27c3960f..408b99a2 100644 --- a/pop-api/src/v0/assets/mod.rs +++ b/pop-api/src/v0/assets/mod.rs @@ -34,14 +34,16 @@ const TRANSFER_APPROVED: u8 = 25; /// Helper method to build a dispatch call `ChainExtensionMethod` for `ASSET` module /// -/// - `dispatchable`: The index of the dispatchable functions in `ASSET` module +/// Parameters: +/// - 'dispatchable': The index of the dispatchable functions in `ASSET` module. fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_dispatch(ASSETS, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` for `ASSET` module /// -/// - `state_query`: The index of the runtime state query +/// Parameters: +/// - 'state_query': The index of the runtime state query. fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { crate::v0::build_read_state(ASSETS, state_query) } From 733e7f0a22c2af67ee25c16d2ab6a093b31e325f Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:30:00 +0800 Subject: [PATCH 08/18] Update mod.rs --- pop-api/src/v0/mod.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 20369154..5fbb6cab 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -25,9 +25,10 @@ impl From for Error { /// Helper method to build `ChainExtensionMethod` for version `v0` /// -/// - `function`: The ID of the function -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'function': The ID of the function +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_extension_method_v0( function: u8, module: u8, @@ -38,16 +39,18 @@ fn build_extension_method_v0( /// Helper method to build a dispatch call `ChainExtensionMethod` /// -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` /// -/// - `module`: The index of the runtime module -/// - `state_query`: The index of the runtime state query +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'state_query': The index of the runtime state query fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(READ_STATE, module, state_query) } From 07c66bee1dd979bc916755deb0b6020cbe939560 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:12:37 +0700 Subject: [PATCH 09/18] remove unused method --- pop-api/src/v0/mod.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 5fbb6cab..f16d9a3b 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -23,27 +23,13 @@ impl From for Error { } } -/// Helper method to build `ChainExtensionMethod` for version `v0` -/// -/// Parameters: -/// - 'function': The ID of the function -/// - 'module': The index of the runtime module -/// - 'dispatchable': The index of the module dispatchable functions -fn build_extension_method_v0( - function: u8, - module: u8, - dispatchable: u8, -) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method(V0, function, module, dispatchable) -} - /// Helper method to build a dispatch call `ChainExtensionMethod` /// /// Parameters: /// - 'module': The index of the runtime module /// - 'dispatchable': The index of the module dispatchable functions fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(DISPATCH, module, dispatchable) + build_extension_method(V0, DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` @@ -52,5 +38,5 @@ fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), /// - 'module': The index of the runtime module /// - 'state_query': The index of the runtime state query fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(READ_STATE, module, state_query) + build_extension_method(V0, READ_STATE, module, state_query) } From 4e4512ef091a9c6322eb17e697b2180c0e210f22 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:45:43 +0700 Subject: [PATCH 10/18] refactor: streamline error from the decoded method by returning `Result` (#130) --- .../integration-tests/src/local_fungibles.rs | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/pop-api/integration-tests/src/local_fungibles.rs b/pop-api/integration-tests/src/local_fungibles.rs index c62f0713..6de57ca4 100644 --- a/pop-api/integration-tests/src/local_fungibles.rs +++ b/pop-api/integration-tests/src/local_fungibles.rs @@ -8,11 +8,9 @@ use pop_primitives::error::{ const ASSET_ID: AssetId = 1; const CONTRACT: &str = "contracts/fungibles/target/ink/fungibles.wasm"; -fn decoded(result: ExecReturnValue) -> T { - match ::decode(&mut &result.data[2..]) { - Ok(value) => value, - Err(_) => panic!("\nTest failed by trying to decode `{:?}` into `T`\n", result), - } +fn decoded(result: ExecReturnValue) -> Result { + ::decode(&mut &result.data[2..]) + .map_err(|_| format!("\nTest failed by trying to decode `{:?}` into `T`\n", result)) } // Call total_supply contract message. @@ -20,7 +18,7 @@ fn total_supply(addr: AccountId32, asset_id: AssetId) -> Balance { let function = function_selector("total_supply"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call balance_of contract message. @@ -28,7 +26,7 @@ fn balance_of(addr: AccountId32, asset_id: AssetId, owner: AccountId32) -> Balan let function = function_selector("balance_of"); let params = [function, asset_id.encode(), owner.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call allowance contract message. @@ -41,7 +39,7 @@ fn allowance( let function = function_selector("allowance"); let params = [function, asset_id.encode(), owner.encode(), spender.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } // Call token_name contract message. @@ -49,7 +47,7 @@ fn token_name(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_name"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result) + decoded::>(result).unwrap() } // Call token_symbol contract message. @@ -57,7 +55,7 @@ fn token_symbol(addr: AccountId32, asset_id: AssetId) -> Vec { let function = function_selector("token_symbol"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::>(result) + decoded::>(result).unwrap() } // Call token_decimals contract message. @@ -65,7 +63,7 @@ fn token_decimals(addr: AccountId32, asset_id: AssetId) -> u8 { let function = function_selector("token_decimals"); let params = [function, asset_id.encode()].concat(); let result = bare_call(addr, params, 0).expect("should work"); - decoded::(result) + decoded::(result).unwrap() } fn transfer( @@ -327,7 +325,7 @@ fn transfer_works() { // Asset does not exist. assert_eq!( decoded::(transfer(addr.clone(), 1, BOB, amount,)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); // Create asset with Alice as owner and mint `amount` to contract address. let asset = create_asset_and_mint_to(ALICE, 1, addr.clone(), amount); @@ -335,18 +333,18 @@ fn transfer_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount,)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Not enough balance. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount + 1 * UNIT)), - Module { index: 52, error: 0 }, + Ok(Module { index: 52, error: 0 }), ); // Not enough balance due to ED. assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 0 }, + Ok(Module { index: 52, error: 0 }), ); // Successful transfer. let balance_before_transfer = Assets::balance(asset, &BOB); @@ -357,13 +355,13 @@ fn transfer_works() { // Transfer asset to account that does not exist. assert_eq!( decoded::(transfer(addr.clone(), asset, FERDIE, amount / 4)), - Token(CannotCreate) + Ok(Token(CannotCreate)) ); // Asset is not live, i.e. frozen or being destroyed. start_destroy_asset(ALICE, asset); assert_eq!( decoded::(transfer(addr.clone(), asset, BOB, amount / 4)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -377,10 +375,13 @@ fn approve_works() { // Asset does not exist. assert_eq!( decoded::(approve(addr.clone(), 0, BOB, amount)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); - assert_eq!(decoded::(approve(addr.clone(), asset, BOB, amount)), ConsumerRemaining); + assert_eq!( + decoded::(approve(addr.clone(), asset, BOB, amount)), + Ok(ConsumerRemaining) + ); let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); // Create asset with Alice as owner and mint `amount` to contract address. @@ -389,7 +390,7 @@ fn approve_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(approve(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Successful approvals: @@ -403,7 +404,7 @@ fn approve_works() { start_destroy_asset(ALICE, asset); assert_eq!( decoded::(approve(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -417,12 +418,12 @@ fn increase_allowance_works() { // Asset does not exist. assert_eq!( decoded::(increase_allowance(addr.clone(), 0, BOB, amount)), - Module { index: 52, error: 3 }, + Ok(Module { index: 52, error: 3 }), ); let asset = create_asset_and_mint_to(ALICE, 0, addr.clone(), amount); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - ConsumerRemaining + Ok(ConsumerRemaining) ); let addr = instantiate(CONTRACT, INIT_VALUE, vec![1]); @@ -432,7 +433,7 @@ fn increase_allowance_works() { freeze_asset(ALICE, asset); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); thaw_asset(ALICE, asset); // Successful approvals: @@ -452,7 +453,7 @@ fn increase_allowance_works() { start_destroy_asset(ALICE, asset); assert_eq!( decoded::(increase_allowance(addr.clone(), asset, BOB, amount)), - Module { index: 52, error: 16 }, + Ok(Module { index: 52, error: 16 }), ); }); } @@ -530,7 +531,7 @@ fn token_metadata_works() { // // Minting can only be done by the owner. // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 2 }, +// Ok(Module { index: 52, error: 2 }), // ); // // Minimum balance of an asset can not be zero. // assert_eq!( @@ -542,7 +543,7 @@ fn token_metadata_works() { // freeze_asset(addr.clone(), asset); // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 16 }, +// Ok(Module { index: 52, error: 16 }), // ); // thaw_asset(addr.clone(), asset); // // Successful mint. @@ -567,7 +568,7 @@ fn token_metadata_works() { // start_destroy_asset(addr.clone(), asset); // assert_eq!( // decoded::(transfer_from(addr.clone(), asset, None, Some(BOB), amount, &[0u8])), -// Module { index: 52, error: 16 }, +// Ok(Module { index: 52, error: 16 }), // ); // }); // } @@ -582,27 +583,27 @@ fn token_metadata_works() { // // No balance to pay for fees. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Module { index: 10, error: 2 }, +// Ok(Module { index: 10, error: 2 }), // ); // // Instantiate a contract without balance (relay token). // let addr = instantiate(CONTRACT, 100, vec![2]); // // No balance to pay the deposit. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, addr.clone(), 1)), -// Module { index: 10, error: 2 }, +// Ok(Module { index: 10, error: 2 }), // ); // // Instantiate a contract with balance. // let addr = // instantiate(CONTRACT, INIT_VALUE, vec![1]); // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, BOB, 0)), -// Module { index: 52, error: 7 }, +// Ok(Module { index: 52, error: 7 }), // ); // create_asset(ALICE, ASSET_ID, 1); // // Asset ID is already taken. // assert_eq!( // decoded::(create(addr.clone(), ASSET_ID, BOB, 1)), -// Module { index: 52, error: 5 }, +// Ok(Module { index: 52, error: 5 }), // ); // // The minimal balance for an asset must be non zero. // let new_asset = 2; From a0452c99b540dc894bd7980a57d29185e97fdfe9 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Sat, 27 Jul 2024 00:01:32 +0700 Subject: [PATCH 11/18] rebase --- pop-api/src/lib.rs | 1 + pop-api/src/utils.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 pop-api/src/utils.rs diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index a984bb9e..424f925a 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -6,6 +6,7 @@ use ink::env::chain_extension::FromStatusCode; pub use v0::assets; pub mod primitives; +pub mod utils; pub mod v0; /// A result type used by the API, with the `StatusCode` as the error type. diff --git a/pop-api/src/utils.rs b/pop-api/src/utils.rs new file mode 100644 index 00000000..59a982f6 --- /dev/null +++ b/pop-api/src/utils.rs @@ -0,0 +1,10 @@ +use ink::env::chain_extension::ChainExtensionMethod; + +pub(crate) fn build_extension_method( + version: u8, + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) +} From c791b459e5e260116239639853d8ecf133e2129b Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:33:39 +0700 Subject: [PATCH 12/18] refractor: simplify the methods --- pop-api/src/lib.rs | 13 ++++++++++++- pop-api/src/utils.rs | 10 ---------- pop-api/src/v0/mod.rs | 27 ++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 12 deletions(-) delete mode 100644 pop-api/src/utils.rs diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 424f925a..f0e38fb1 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,12 +1,13 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] +use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; + use constants::DECODING_FAILED; use ink::env::chain_extension::FromStatusCode; #[cfg(feature = "assets")] pub use v0::assets; pub mod primitives; -pub mod utils; pub mod v0; /// A result type used by the API, with the `StatusCode` as the error type. @@ -28,6 +29,16 @@ mod constants { pub(crate) const FUNGIBLES: u8 = 150; } +/// Helper method to build `ChainExtensionMethod`` +pub fn build_extension_method( + version: u8, + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) +} + /// Represents a status code returned by the runtime. /// /// `StatusCode` encapsulates a `u32` value that indicates the status of an operation performed diff --git a/pop-api/src/utils.rs b/pop-api/src/utils.rs deleted file mode 100644 index 59a982f6..00000000 --- a/pop-api/src/utils.rs +++ /dev/null @@ -1,10 +0,0 @@ -use ink::env::chain_extension::ChainExtensionMethod; - -pub(crate) fn build_extension_method( - version: u8, - function: u8, - module: u8, - dispatchable: u8, -) -> ChainExtensionMethod<(), (), (), false> { - ChainExtensionMethod::build(u32::from_le_bytes([version, function, module, dispatchable])) -} diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 1c3642e1..c95aba38 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -1,4 +1,10 @@ -use crate::{primitives::error::Error, StatusCode}; +use crate::{ + build_extension_method, + constants::{DISPATCH, READ_STATE}, + primitives::error::Error, + StatusCode, +}; +use ink::env::chain_extension::ChainExtensionMethod; #[cfg(feature = "assets")] pub mod assets; @@ -10,3 +16,22 @@ impl From for Error { value.0.into() } } + +/// Helper method to build `ChainExtensionMethod`` +pub fn build_extension_method_v0( + function: u8, + module: u8, + dispatchable: u8, +) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method(V0, function, module, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` +pub fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(DISPATCH, module, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` +pub fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(READ_STATE, module, dispatchable) +} From 83ee99c123c7062404058140c4536c429bf8320c Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:48:34 +0700 Subject: [PATCH 13/18] refractor --- pop-api/src/lib.rs | 7 ++++++- pop-api/src/v0/mod.rs | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index f0e38fb1..eebf232f 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -30,7 +30,12 @@ mod constants { } /// Helper method to build `ChainExtensionMethod`` -pub fn build_extension_method( +/// +/// - `version`: The version of the chain extension +/// - `function`: The ID of the function +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_extension_method( version: u8, function: u8, module: u8, diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index c95aba38..31075493 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -17,8 +17,12 @@ impl From for Error { } } -/// Helper method to build `ChainExtensionMethod`` -pub fn build_extension_method_v0( +/// Helper method to build `ChainExtensionMethod` for version `v0` +/// +/// - `function`: The ID of the function +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_extension_method_v0( function: u8, module: u8, dispatchable: u8, @@ -27,11 +31,17 @@ pub fn build_extension_method_v0( } /// Helper method to build a dispatch call `ChainExtensionMethod` -pub fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { +/// +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` -pub fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { +/// +/// - `module`: The index of the runtime module +/// - `dispatchable`: The index of the module dispatchable functions +fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(READ_STATE, module, dispatchable) } From 9818c695b70ad1be77ccc8b8c0717c64f8dc9a1c Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 18:50:52 +0700 Subject: [PATCH 14/18] hotfix: build_state_query parameter name --- pop-api/src/v0/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 31075493..be074b4f 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -41,7 +41,7 @@ fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), /// Helper method to build a dispatch call `ChainExtensionMethod` /// /// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions -fn build_read_state(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(READ_STATE, module, dispatchable) +/// - `state_query`: The index of the runtime state query +fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + build_extension_method_v0(READ_STATE, module, state_query) } From 4344d9a550adbdcbf46b9bff415f4172565d3e56 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:27:24 +0800 Subject: [PATCH 15/18] update comment --- pop-api/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index eebf232f..9bf9d50b 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -29,12 +29,13 @@ mod constants { pub(crate) const FUNGIBLES: u8 = 150; } -/// Helper method to build `ChainExtensionMethod`` +/// Helper method to build `ChainExtensionMethod`. /// -/// - `version`: The version of the chain extension -/// - `function`: The ID of the function -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'version': The version of the chain extension +/// - 'function': The ID of the function +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_extension_method( version: u8, function: u8, From ccb3d7511368fdc7bd968ff75d3eeb1d05cbf252 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 24 Jul 2024 20:30:00 +0800 Subject: [PATCH 16/18] Update mod.rs --- pop-api/src/v0/mod.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index be074b4f..3a738387 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -19,9 +19,10 @@ impl From for Error { /// Helper method to build `ChainExtensionMethod` for version `v0` /// -/// - `function`: The ID of the function -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'function': The ID of the function +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_extension_method_v0( function: u8, module: u8, @@ -32,16 +33,18 @@ fn build_extension_method_v0( /// Helper method to build a dispatch call `ChainExtensionMethod` /// -/// - `module`: The index of the runtime module -/// - `dispatchable`: The index of the module dispatchable functions +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'dispatchable': The index of the module dispatchable functions fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` /// -/// - `module`: The index of the runtime module -/// - `state_query`: The index of the runtime state query +/// Parameters: +/// - 'module': The index of the runtime module +/// - 'state_query': The index of the runtime state query fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { build_extension_method_v0(READ_STATE, module, state_query) } From ab5498ef601a5ad6c1020cf9734daa7d7aad836a Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:12:37 +0700 Subject: [PATCH 17/18] remove unused method --- pop-api/src/v0/mod.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index 3a738387..0fd06c89 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -17,27 +17,13 @@ impl From for Error { } } -/// Helper method to build `ChainExtensionMethod` for version `v0` -/// -/// Parameters: -/// - 'function': The ID of the function -/// - 'module': The index of the runtime module -/// - 'dispatchable': The index of the module dispatchable functions -fn build_extension_method_v0( - function: u8, - module: u8, - dispatchable: u8, -) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method(V0, function, module, dispatchable) -} - /// Helper method to build a dispatch call `ChainExtensionMethod` /// /// Parameters: /// - 'module': The index of the runtime module /// - 'dispatchable': The index of the module dispatchable functions fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(DISPATCH, module, dispatchable) + build_extension_method(V0, DISPATCH, module, dispatchable) } /// Helper method to build a dispatch call `ChainExtensionMethod` @@ -46,5 +32,5 @@ fn build_dispatch(module: u8, dispatchable: u8) -> ChainExtensionMethod<(), (), /// - 'module': The index of the runtime module /// - 'state_query': The index of the runtime state query fn build_read_state(module: u8, state_query: u8) -> ChainExtensionMethod<(), (), (), false> { - build_extension_method_v0(READ_STATE, module, state_query) + build_extension_method(V0, READ_STATE, module, state_query) } From cfd993d7ee0dc53c55357e7a1a13d38fc7a73211 Mon Sep 17 00:00:00 2001 From: tin-snowflake <56880684+chungquantin@users.noreply.github.com> Date: Sat, 27 Jul 2024 00:08:49 +0700 Subject: [PATCH 18/18] refactor: reduce chain extension method code --- pop-api/src/v0/assets/fungibles.rs | 38 +++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/pop-api/src/v0/assets/fungibles.rs b/pop-api/src/v0/assets/fungibles.rs index 42373cd7..68ce76b8 100644 --- a/pop-api/src/v0/assets/fungibles.rs +++ b/pop-api/src/v0/assets/fungibles.rs @@ -9,6 +9,22 @@ use crate::{ use constants::*; pub use metadata::*; +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0` +/// +/// Parameters: +/// - 'dispatchable': The index of the module dispatchable functions +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_dispatch(FUNGIBLES, dispatchable) +} + +/// Helper method to build a dispatch call `ChainExtensionMethod` for fungibles `v0`` +/// +/// Parameters: +/// - 'state_query': The index of the runtime state query +fn build_read_state(state_query: u8) -> ChainExtensionMethod<(), (), (), false> { + crate::v0::build_read_state(FUNGIBLES, state_query) +} + /// Local Fungibles: /// 1. PSP-22 Interface /// 2. PSP-22 Metadata Interface @@ -60,7 +76,7 @@ mod constants { /// The total supply of the token, or an error if the operation fails. #[inline] pub fn total_supply(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOTAL_SUPPLY])) + build_read_state(TOTAL_SUPPLY) .input::() .output::>, true>() .handle_error_code::() @@ -79,7 +95,7 @@ pub fn total_supply(id: AssetId) -> Result { /// The balance of the specified account, or an error if the operation fails. #[inline] pub fn balance_of(id: AssetId, owner: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, BALANCE_OF])) + build_read_state(BALANCE_OF) .input::<(AssetId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -99,7 +115,7 @@ pub fn balance_of(id: AssetId, owner: AccountId) -> Result { /// The remaining allowance, or an error if the operation fails. #[inline] pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, ALLOWANCE])) + build_read_state(ALLOWANCE) .input::<(AssetId, AccountId, AccountId)>() .output::>, true>() .handle_error_code::() @@ -119,7 +135,7 @@ pub fn allowance(id: AssetId, owner: AccountId, spender: AccountId) -> Result Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER])) + build_dispatch(TRANSFER) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -140,7 +156,7 @@ pub fn transfer(id: AssetId, target: AccountId, amount: Balance) -> Result<()> { /// Returns `Ok(())` if successful, or an error if the transfer fails. #[inline] pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, TRANSFER_FROM])) + build_dispatch(TRANSFER_FROM) .input::<(AssetId, AccountId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -158,7 +174,7 @@ pub fn transfer_from(id: AssetId, from: AccountId, to: AccountId, amount: Balanc /// Returns `Ok(())` if successful, or an error if the approval fails. #[inline] pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, APPROVE])) + build_dispatch(APPROVE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -176,7 +192,7 @@ pub fn approve(id: AssetId, spender: AccountId, amount: Balance) -> Result<()> { /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, INCREASE_ALLOWANCE])) + build_dispatch(INCREASE_ALLOWANCE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -194,7 +210,7 @@ pub fn increase_allowance(id: AssetId, spender: AccountId, value: Balance) -> Re /// Returns `Ok(())` if successful, or an error if the operation fails. #[inline] pub fn decrease_allowance(id: AssetId, spender: AccountId, value: Balance) -> Result<()> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, DISPATCH, FUNGIBLES, DECREASE_ALLOWANCE])) + build_dispatch(DECREASE_ALLOWANCE) .input::<(AssetId, AccountId, Balance)>() .output::, true>() .handle_error_code::() @@ -212,7 +228,7 @@ pub mod metadata { /// The name of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_name(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_NAME])) + build_read_state(TOKEN_NAME) .input::() .output::>, true>() .handle_error_code::() @@ -229,7 +245,7 @@ pub mod metadata { /// The symbol of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_symbol(id: AssetId) -> Result> { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_SYMBOL])) + build_read_state(TOKEN_SYMBOL) .input::() .output::>, true>() .handle_error_code::() @@ -246,7 +262,7 @@ pub mod metadata { /// The number of decimals of the token as a byte vector, or an error if the operation fails. #[inline] pub fn token_decimals(id: AssetId) -> Result { - ChainExtensionMethod::build(u32::from_le_bytes([V0, READ_STATE, FUNGIBLES, TOKEN_DECIMALS])) + build_read_state(TOKEN_DECIMALS) .input::() .output::>, true>() .handle_error_code::()