fix: EnsureOrigin try_successful_origin and snowbridge rename
- Fix pezpallet-welati EnsureOrigin implementations (3 fixes)
- Remove incorrect #[cfg(not(feature = "runtime-benchmarks"))] blocks
- Affects EnsureSerok, EnsureParlementer, EnsureDiwan
- Fix asset-hub-zagros governance origins macros (2 fixes)
- Remove non-benchmark try_successful_origin from decl_unit_ensures!
- Remove non-benchmark try_successful_origin from decl_ensure!
- Rename snowbridge -> pezsnowbridge for consistency
- Update WORKFLOW_PLAN.md with build status and package names
- Correct package names: pezkuwi-teyrchain-bin, pezstaging-node-cli
- Mark completed builds: pezkuwi, pezkuwi-teyrchain-bin,
pezstaging-node-cli, teyrchain-template-node
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
pub mod mock_converter;
|
||||
pub mod mock_inbound_queue;
|
||||
pub mod mock_origin;
|
||||
pub mod mock_outbound_queue;
|
||||
pub mod mock_rewards;
|
||||
pub mod mock_swap_executor;
|
||||
pub mod mock_xcm;
|
||||
|
||||
pub const FAILING_NONCE: u64 = 3;
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
use codec::Encode;
|
||||
use pezframe_support::pezsp_runtime::traits::MaybeConvert;
|
||||
use pezsnowbridge_core::TokenIdOf;
|
||||
use pezsp_core::H256;
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
use xcm::{
|
||||
latest::InteriorLocation,
|
||||
prelude::{Location, Reanchorable},
|
||||
};
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
thread_local! {
|
||||
pub static IDENTIFIER_TO_LOCATION: RefCell<HashMap<H256, Location>> = RefCell::new(HashMap::new());
|
||||
pub static LOCATION_TO_IDENTIFIER: RefCell<HashMap<Vec<u8>, H256>> = RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub fn add_location_override(location: Location, ethereum: Location, bh_context: InteriorLocation) {
|
||||
let (token_id, reanchored_location) = reanchor_to_ethereum(location, ethereum, bh_context);
|
||||
IDENTIFIER_TO_LOCATION.with(|b| b.borrow_mut().insert(token_id, reanchored_location.clone()));
|
||||
LOCATION_TO_IDENTIFIER.with(|b| b.borrow_mut().insert(reanchored_location.encode(), token_id));
|
||||
}
|
||||
|
||||
pub fn reanchor_to_ethereum(
|
||||
location: Location,
|
||||
ethereum: Location,
|
||||
bh_context: InteriorLocation,
|
||||
) -> (H256, Location) {
|
||||
let mut reanchored_lol = location.clone();
|
||||
let _ = reanchored_lol.reanchor(ðereum, &bh_context);
|
||||
let token_id = TokenIdOf::convert_location(&reanchored_lol).unwrap();
|
||||
(token_id, reanchored_lol)
|
||||
}
|
||||
|
||||
pub struct LocationIdConvert;
|
||||
impl MaybeConvert<H256, Location> for LocationIdConvert {
|
||||
fn maybe_convert(id: H256) -> Option<Location> {
|
||||
IDENTIFIER_TO_LOCATION.with(|b| b.borrow().get(&id).and_then(|l| Option::from(l.clone())))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
use crate::FAILING_NONCE;
|
||||
use pezsnowbridge_core::reward::{AddTip, AddTipError};
|
||||
|
||||
pub struct MockOkInboundQueue;
|
||||
|
||||
impl AddTip for MockOkInboundQueue {
|
||||
fn add_tip(nonce: u64, _amount: u128) -> Result<(), AddTipError> {
|
||||
// Force an error condition
|
||||
if nonce == FAILING_NONCE {
|
||||
return Err(AddTipError::NonceConsumed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
// A stripped-down version of pezpallet-xcm that only inserts an XCM origin into the runtime
|
||||
#[pezframe_support::pezpallet]
|
||||
pub mod pezpallet_xcm_origin {
|
||||
use codec::DecodeWithMemTracking;
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::*,
|
||||
traits::{Contains, OriginTrait},
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
#[pezpallet::pezpallet]
|
||||
pub struct Pezpallet<T>(_);
|
||||
|
||||
#[pezpallet::config]
|
||||
pub trait Config: pezframe_system::Config {
|
||||
type RuntimeOrigin: From<Origin> + From<<Self as pezframe_system::Config>::RuntimeOrigin>;
|
||||
}
|
||||
|
||||
// Insert this custom Origin into the aggregate RuntimeOrigin
|
||||
#[pezpallet::origin]
|
||||
#[derive(
|
||||
PartialEq,
|
||||
Eq,
|
||||
Clone,
|
||||
Encode,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
RuntimeDebug,
|
||||
TypeInfo,
|
||||
MaxEncodedLen,
|
||||
)]
|
||||
pub struct Origin(pub Location);
|
||||
|
||||
impl From<Location> for Origin {
|
||||
fn from(location: Location) -> Origin {
|
||||
Origin(location)
|
||||
}
|
||||
}
|
||||
|
||||
/// `EnsureOrigin` implementation succeeding with a `Location` value to recognize and
|
||||
/// filter the contained location
|
||||
pub struct EnsureXcm<F>(PhantomData<F>);
|
||||
impl<O: OriginTrait + From<Origin>, F: Contains<Location>> EnsureOrigin<O> for EnsureXcm<F>
|
||||
where
|
||||
O::PalletsOrigin: From<Origin> + TryInto<Origin, Error = O::PalletsOrigin>,
|
||||
{
|
||||
type Success = Location;
|
||||
|
||||
fn try_origin(outer: O) -> Result<Self::Success, O> {
|
||||
outer.try_with_caller(|caller| {
|
||||
caller.try_into().and_then(|o| match o {
|
||||
Origin(location) if F::contains(&location) => Ok(location),
|
||||
o => Err(o.into()),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn try_successful_origin() -> Result<O, ()> {
|
||||
Ok(O::from(Origin(Location::here().into())))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
use crate::FAILING_NONCE;
|
||||
use pezsnowbridge_core::reward::{AddTip, AddTipError};
|
||||
use pezsnowbridge_outbound_queue_primitives::{
|
||||
v1::{Fee, Message as MessageV1, SendMessage as SendMessageV1},
|
||||
v2::{Message, SendMessage},
|
||||
SendMessageFeeProvider,
|
||||
};
|
||||
use pezsp_core::H256;
|
||||
|
||||
pub struct MockOkOutboundQueue;
|
||||
impl SendMessage for MockOkOutboundQueue {
|
||||
type Ticket = ();
|
||||
|
||||
fn validate(
|
||||
_: &Message,
|
||||
) -> Result<Self::Ticket, pezsnowbridge_outbound_queue_primitives::SendError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deliver(
|
||||
_: Self::Ticket,
|
||||
) -> Result<H256, pezsnowbridge_outbound_queue_primitives::SendError> {
|
||||
Ok(H256::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl SendMessageFeeProvider for MockOkOutboundQueue {
|
||||
type Balance = u128;
|
||||
|
||||
fn local_fee() -> Self::Balance {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl AddTip for MockOkOutboundQueue {
|
||||
fn add_tip(nonce: u64, _amount: u128) -> Result<(), AddTipError> {
|
||||
if nonce == FAILING_NONCE {
|
||||
return Err(AddTipError::NonceConsumed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockOkOutboundQueueV1;
|
||||
impl SendMessageV1 for MockOkOutboundQueueV1 {
|
||||
type Ticket = ();
|
||||
|
||||
fn validate(
|
||||
_: &MessageV1,
|
||||
) -> Result<
|
||||
(Self::Ticket, Fee<<Self as SendMessageFeeProvider>::Balance>),
|
||||
pezsnowbridge_outbound_queue_primitives::SendError,
|
||||
> {
|
||||
Ok(((), Fee::from((0, 0))))
|
||||
}
|
||||
|
||||
fn deliver(
|
||||
_: Self::Ticket,
|
||||
) -> Result<H256, pezsnowbridge_outbound_queue_primitives::SendError> {
|
||||
Ok(H256::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl SendMessageFeeProvider for MockOkOutboundQueueV1 {
|
||||
type Balance = u128;
|
||||
|
||||
fn local_fee() -> Self::Balance {
|
||||
0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
use bp_relayers::{PaymentProcedure, RewardLedger, RewardsAccountOwner, RewardsAccountParams};
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use pezframe_support::{parameter_types, pezpallet_prelude::DispatchResult, pezsp_runtime};
|
||||
use scale_info::TypeInfo;
|
||||
use xcm::opaque::latest::Location;
|
||||
|
||||
/// Showcasing that we can handle multiple different rewards with the same pezpallet.
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Encode,
|
||||
Eq,
|
||||
MaxEncodedLen,
|
||||
PartialEq,
|
||||
TypeInfo,
|
||||
)]
|
||||
pub enum BridgeReward {
|
||||
/// Rewards for Snowbridge.
|
||||
Snowbridge,
|
||||
}
|
||||
|
||||
pub struct MockPaymentProcedure;
|
||||
|
||||
// Provide a no-op or mock implementation for the required trait
|
||||
impl PaymentProcedure<pezsp_runtime::AccountId32, RewardsAccountParams<u64>, u128>
|
||||
for MockPaymentProcedure
|
||||
{
|
||||
type Error = DispatchResult;
|
||||
type Beneficiary = Location;
|
||||
fn pay_reward(
|
||||
_who: &pezsp_runtime::AccountId32,
|
||||
_reward_params: bp_relayers::RewardsAccountParams<u64>,
|
||||
_reward_balance: u128,
|
||||
_beneficiary: Self::Beneficiary,
|
||||
) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BridgeReward> for RewardsAccountParams<u64> {
|
||||
fn from(_bridge_reward: BridgeReward) -> Self {
|
||||
RewardsAccountParams::new(1, [0; 4], RewardsAccountOwner::ThisChain)
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static RegisteredRewardsCount: u128 = 0;
|
||||
pub static RegisteredRewardAmount: u128 = 0;
|
||||
}
|
||||
|
||||
pub struct MockRewardLedger;
|
||||
|
||||
impl RewardLedger<pezsp_runtime::AccountId32, BridgeReward, u128> for MockRewardLedger {
|
||||
fn register_reward(
|
||||
_relayer: &pezsp_runtime::AccountId32,
|
||||
_reward: BridgeReward,
|
||||
reward_balance: u128,
|
||||
) {
|
||||
RegisteredRewardsCount::set(RegisteredRewardsCount::get().saturating_add(1));
|
||||
RegisteredRewardAmount::set(reward_balance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
use pezframe_support::pezpallet_prelude::DispatchError;
|
||||
use pezpallet_asset_conversion::Swap;
|
||||
use xcm::opaque::latest::Location;
|
||||
pub struct SwapExecutor;
|
||||
|
||||
pub const TRIGGER_SWAP_ERROR_AMOUNT: u128 = 12345;
|
||||
|
||||
impl<AccountId> Swap<AccountId> for SwapExecutor
|
||||
where
|
||||
AccountId: AsRef<[u8; 32]>,
|
||||
{
|
||||
type Balance = u128;
|
||||
type AssetKind = Location;
|
||||
|
||||
fn max_path_len() -> u32 {
|
||||
2
|
||||
}
|
||||
|
||||
fn swap_exact_tokens_for_tokens(
|
||||
_sender: AccountId,
|
||||
_path: Vec<Self::AssetKind>,
|
||||
amount_in: Self::Balance,
|
||||
_amount_out_min: Option<Self::Balance>,
|
||||
_send_to: AccountId,
|
||||
_keep_alive: bool,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
// Special case for testing SwapError:
|
||||
// If amount_in is exactly 12345, return an error
|
||||
if amount_in == TRIGGER_SWAP_ERROR_AMOUNT {
|
||||
return Err(DispatchError::Other("Swap failed for test"));
|
||||
}
|
||||
Ok(1_000_000_000u128)
|
||||
}
|
||||
|
||||
fn swap_tokens_for_exact_tokens(
|
||||
_sender: AccountId,
|
||||
_path: Vec<Self::AssetKind>,
|
||||
_amount_out: Self::Balance,
|
||||
_amount_in_max: Option<Self::Balance>,
|
||||
_send_to: AccountId,
|
||||
_keep_alive: bool,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
|
||||
use codec::Encode;
|
||||
use core::cell::RefCell;
|
||||
use xcm::prelude::*;
|
||||
use xcm_executor::{
|
||||
traits::{FeeManager, FeeReason, TransactAsset},
|
||||
AssetsInHolding,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
pub static IS_WAIVED: RefCell<Vec<FeeReason>> = RefCell::new(vec![]);
|
||||
pub static SENDER_OVERRIDE: RefCell<Option<(
|
||||
fn(
|
||||
&mut Option<Location>,
|
||||
&mut Option<Xcm<()>>,
|
||||
) -> Result<(Xcm<()>, Assets), SendError>,
|
||||
fn(
|
||||
Xcm<()>,
|
||||
) -> Result<XcmHash, SendError>,
|
||||
)>> = RefCell::new(None);
|
||||
pub static CHARGE_FEES_OVERRIDE: RefCell<Option<
|
||||
fn(Location, Assets) -> xcm::latest::Result
|
||||
>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_fee_waiver(waived: Vec<FeeReason>) {
|
||||
IS_WAIVED.with(|l| l.replace(waived));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_sender_override(
|
||||
validate: fn(&mut Option<Location>, &mut Option<Xcm<()>>) -> SendResult<Xcm<()>>,
|
||||
deliver: fn(Xcm<()>) -> Result<XcmHash, SendError>,
|
||||
) {
|
||||
SENDER_OVERRIDE.with(|x| x.replace(Some((validate, deliver))));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn clear_sender_override() {
|
||||
SENDER_OVERRIDE.with(|x| x.replace(None));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_charge_fees_override(charge_fees: fn(Location, Assets) -> xcm::latest::Result) {
|
||||
CHARGE_FEES_OVERRIDE.with(|x| x.replace(Some(charge_fees)));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn clear_charge_fees_override() {
|
||||
CHARGE_FEES_OVERRIDE.with(|x| x.replace(None));
|
||||
}
|
||||
|
||||
/// Mock XCM sender with an overridable `validate` and `deliver` function.
|
||||
pub struct MockXcmSender;
|
||||
|
||||
impl SendXcm for MockXcmSender {
|
||||
type Ticket = Xcm<()>;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<Location>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
let r: SendResult<Self::Ticket> = SENDER_OVERRIDE.with(|s| {
|
||||
if let Some((ref f, _)) = &*s.borrow() {
|
||||
f(dest, xcm)
|
||||
} else {
|
||||
Ok((xcm.take().unwrap(), Assets::default()))
|
||||
}
|
||||
});
|
||||
r
|
||||
}
|
||||
|
||||
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
|
||||
let r: Result<XcmHash, SendError> = SENDER_OVERRIDE.with(|s| {
|
||||
if let Some((_, ref f)) = &*s.borrow() {
|
||||
f(ticket)
|
||||
} else {
|
||||
let hash = ticket.using_encoded(pezsp_core::hashing::blake2_256);
|
||||
Ok(hash)
|
||||
}
|
||||
});
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
/// Mock XCM transactor that always succeeds
|
||||
pub struct SuccessfulTransactor;
|
||||
impl TransactAsset for SuccessfulTransactor {
|
||||
fn can_check_in(_origin: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn can_check_out(_dest: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deposit_asset(_what: &Asset, _who: &Location, _context: Option<&XcmContext>) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
_what: &Asset,
|
||||
_who: &Location,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
Ok(AssetsInHolding::default())
|
||||
}
|
||||
|
||||
fn internal_transfer_asset(
|
||||
_what: &Asset,
|
||||
_from: &Location,
|
||||
_to: &Location,
|
||||
_context: &XcmContext,
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
Ok(AssetsInHolding::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Weightless {}
|
||||
impl PreparedMessage for Weightless {
|
||||
fn weight_of(&self) -> Weight {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
/// Mock the XCM executor with an overridable `charge_fees` function.
|
||||
pub struct MockXcmExecutor;
|
||||
impl<C> ExecuteXcm<C> for MockXcmExecutor {
|
||||
type Prepared = Weightless;
|
||||
fn prepare(_: Xcm<C>, _: Weight) -> Result<Self::Prepared, InstructionError> {
|
||||
unreachable!()
|
||||
}
|
||||
fn execute(_: impl Into<Location>, _: Self::Prepared, _: &mut XcmHash, _: Weight) -> Outcome {
|
||||
unreachable!()
|
||||
}
|
||||
fn charge_fees(location: impl Into<Location>, assets: Assets) -> xcm::latest::Result {
|
||||
let r: xcm::latest::Result = CHARGE_FEES_OVERRIDE.with(|s| {
|
||||
if let Some(ref f) = &*s.borrow() {
|
||||
f(location.into(), assets)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
impl FeeManager for MockXcmExecutor {
|
||||
fn is_waived(_: Option<&Location>, r: FeeReason) -> bool {
|
||||
IS_WAIVED.with(|l| l.borrow().contains(&r))
|
||||
}
|
||||
|
||||
fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) {}
|
||||
}
|
||||
Reference in New Issue
Block a user