feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Ensure we're `no_std` when compiling for Wasm.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::marker::PhantomData;
|
||||
use ethereum_standards::{
|
||||
IERC20,
|
||||
IERC20::{IERC20Calls, IERC20Events},
|
||||
};
|
||||
use pezpallet_assets::{weights::WeightInfo, Call, Config, TransferFlags};
|
||||
use pezpallet_revive::precompiles::{
|
||||
alloy::{
|
||||
self,
|
||||
primitives::IntoLogData,
|
||||
sol_types::{Revert, SolCall},
|
||||
},
|
||||
AddressMapper, AddressMatcher, Error, Ext, Precompile, RuntimeCosts, H160, H256,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Mean of extracting the asset id from the precompile address.
|
||||
pub trait AssetIdExtractor {
|
||||
type AssetId;
|
||||
/// Extracts the asset id from the address.
|
||||
fn asset_id_from_address(address: &[u8; 20]) -> Result<Self::AssetId, Error>;
|
||||
}
|
||||
|
||||
/// The configuration of a pezpallet-assets precompile.
|
||||
pub trait AssetPrecompileConfig {
|
||||
/// The Address matcher used by the precompile.
|
||||
const MATCHER: AddressMatcher;
|
||||
|
||||
/// The [`AssetIdExtractor`] used by the precompile.
|
||||
type AssetIdExtractor: AssetIdExtractor;
|
||||
}
|
||||
|
||||
/// An `AssetIdExtractor` that stores the asset id directly inside the address.
|
||||
pub struct InlineAssetIdExtractor;
|
||||
|
||||
impl AssetIdExtractor for InlineAssetIdExtractor {
|
||||
type AssetId = u32;
|
||||
fn asset_id_from_address(addr: &[u8; 20]) -> Result<Self::AssetId, Error> {
|
||||
let bytes: [u8; 4] = addr[0..4].try_into().expect("slice is 4 bytes; qed");
|
||||
let index = u32::from_be_bytes(bytes);
|
||||
return Ok(index.into());
|
||||
}
|
||||
}
|
||||
|
||||
/// A precompile configuration that uses a prefix [`AddressMatcher`].
|
||||
pub struct InlineIdConfig<const PREFIX: u16>;
|
||||
|
||||
impl<const P: u16> AssetPrecompileConfig for InlineIdConfig<P> {
|
||||
const MATCHER: AddressMatcher = AddressMatcher::Prefix(core::num::NonZero::new(P).unwrap());
|
||||
type AssetIdExtractor = InlineAssetIdExtractor;
|
||||
}
|
||||
|
||||
/// An ERC20 precompile.
|
||||
pub struct ERC20<Runtime, PrecompileConfig, Instance = ()> {
|
||||
_phantom: PhantomData<(Runtime, PrecompileConfig, Instance)>,
|
||||
}
|
||||
|
||||
impl<Runtime, PrecompileConfig, Instance: 'static> Precompile
|
||||
for ERC20<Runtime, PrecompileConfig, Instance>
|
||||
where
|
||||
PrecompileConfig: AssetPrecompileConfig,
|
||||
Runtime: crate::Config<Instance> + pezpallet_revive::Config,
|
||||
<<PrecompileConfig as AssetPrecompileConfig>::AssetIdExtractor as AssetIdExtractor>::AssetId:
|
||||
Into<<Runtime as Config<Instance>>::AssetId>,
|
||||
Call<Runtime, Instance>: Into<<Runtime as pezpallet_revive::Config>::RuntimeCall>,
|
||||
alloy::primitives::U256: TryInto<<Runtime as Config<Instance>>::Balance>,
|
||||
|
||||
// Note can't use From as it's not implemented for alloy::primitives::U256 for unsigned types
|
||||
alloy::primitives::U256: TryFrom<<Runtime as Config<Instance>>::Balance>,
|
||||
{
|
||||
type T = Runtime;
|
||||
type Interface = IERC20::IERC20Calls;
|
||||
const MATCHER: AddressMatcher = PrecompileConfig::MATCHER;
|
||||
const HAS_CONTRACT_INFO: bool = false;
|
||||
|
||||
fn call(
|
||||
address: &[u8; 20],
|
||||
input: &Self::Interface,
|
||||
env: &mut impl Ext<T = Self::T>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
let asset_id = PrecompileConfig::AssetIdExtractor::asset_id_from_address(address)?.into();
|
||||
|
||||
match input {
|
||||
IERC20Calls::transfer(_) | IERC20Calls::approve(_) | IERC20Calls::transferFrom(_)
|
||||
if env.is_read_only() =>
|
||||
Err(Error::Error(pezpallet_revive::Error::<Self::T>::StateChangeDenied.into())),
|
||||
|
||||
IERC20Calls::transfer(call) => Self::transfer(asset_id, call, env),
|
||||
IERC20Calls::totalSupply(_) => Self::total_supply(asset_id, env),
|
||||
IERC20Calls::balanceOf(call) => Self::balance_of(asset_id, call, env),
|
||||
IERC20Calls::allowance(call) => Self::allowance(asset_id, call, env),
|
||||
IERC20Calls::approve(call) => Self::approve(asset_id, call, env),
|
||||
IERC20Calls::transferFrom(call) => Self::transfer_from(asset_id, call, env),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ERR_INVALID_CALLER: &str = "Invalid caller";
|
||||
const ERR_BALANCE_CONVERSION_FAILED: &str = "Balance conversion failed";
|
||||
|
||||
impl<Runtime, PrecompileConfig, Instance: 'static> ERC20<Runtime, PrecompileConfig, Instance>
|
||||
where
|
||||
PrecompileConfig: AssetPrecompileConfig,
|
||||
Runtime: crate::Config<Instance> + pezpallet_revive::Config,
|
||||
<<PrecompileConfig as AssetPrecompileConfig>::AssetIdExtractor as AssetIdExtractor>::AssetId:
|
||||
Into<<Runtime as Config<Instance>>::AssetId>,
|
||||
Call<Runtime, Instance>: Into<<Runtime as pezpallet_revive::Config>::RuntimeCall>,
|
||||
alloy::primitives::U256: TryInto<<Runtime as Config<Instance>>::Balance>,
|
||||
|
||||
// Note can't use From as it's not implemented for alloy::primitives::U256 for unsigned types
|
||||
alloy::primitives::U256: TryFrom<<Runtime as Config<Instance>>::Balance>,
|
||||
{
|
||||
/// Get the caller as an `H160` address.
|
||||
fn caller(env: &mut impl Ext<T = Runtime>) -> Result<H160, Error> {
|
||||
env.caller()
|
||||
.account_id()
|
||||
.map(<Runtime as pezpallet_revive::Config>::AddressMapper::to_address)
|
||||
.map_err(|_| Error::Revert(Revert { reason: ERR_INVALID_CALLER.into() }))
|
||||
}
|
||||
|
||||
/// Convert a `U256` value to the balance type of the pallet.
|
||||
fn to_balance(
|
||||
value: alloy::primitives::U256,
|
||||
) -> Result<<Runtime as Config<Instance>>::Balance, Error> {
|
||||
value
|
||||
.try_into()
|
||||
.map_err(|_| Error::Revert(Revert { reason: ERR_BALANCE_CONVERSION_FAILED.into() }))
|
||||
}
|
||||
|
||||
/// Convert a balance to a `U256` value.
|
||||
/// Note this is needed cause From is not implemented for unsigned integer types
|
||||
fn to_u256(
|
||||
value: <Runtime as Config<Instance>>::Balance,
|
||||
) -> Result<alloy::primitives::U256, Error> {
|
||||
alloy::primitives::U256::try_from(value)
|
||||
.map_err(|_| Error::Revert(Revert { reason: ERR_BALANCE_CONVERSION_FAILED.into() }))
|
||||
}
|
||||
|
||||
/// Deposit an event to the runtime.
|
||||
fn deposit_event(env: &mut impl Ext<T = Runtime>, event: IERC20Events) -> Result<(), Error> {
|
||||
let (topics, data) = event.into_log_data().split();
|
||||
let topics = topics.into_iter().map(|v| H256(v.0)).collect::<Vec<_>>();
|
||||
env.gas_meter_mut().charge(RuntimeCosts::DepositEvent {
|
||||
num_topic: topics.len() as u32,
|
||||
len: topics.len() as u32,
|
||||
})?;
|
||||
env.deposit_event(topics, data.to_vec());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Execute the transfer call.
|
||||
fn transfer(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
call: &IERC20::transferCall,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::transfer())?;
|
||||
|
||||
let from = Self::caller(env)?;
|
||||
let dest = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(
|
||||
&call.to.into_array().into(),
|
||||
);
|
||||
|
||||
let f = TransferFlags { keep_alive: false, best_effort: false, burn_dust: false };
|
||||
pezpallet_assets::Pallet::<Runtime, Instance>::do_transfer(
|
||||
asset_id,
|
||||
&<Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&from),
|
||||
&dest,
|
||||
Self::to_balance(call.value)?,
|
||||
None,
|
||||
f,
|
||||
)?;
|
||||
|
||||
Self::deposit_event(
|
||||
env,
|
||||
IERC20Events::Transfer(IERC20::Transfer {
|
||||
from: from.0.into(),
|
||||
to: call.to,
|
||||
value: call.value,
|
||||
}),
|
||||
)?;
|
||||
|
||||
return Ok(IERC20::transferCall::abi_encode_returns(&true));
|
||||
}
|
||||
|
||||
/// Execute the total supply call.
|
||||
fn total_supply(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
use pezframe_support::traits::fungibles::Inspect;
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::total_issuance())?;
|
||||
|
||||
let value =
|
||||
Self::to_u256(pezpallet_assets::Pallet::<Runtime, Instance>::total_issuance(asset_id))?;
|
||||
return Ok(IERC20::totalSupplyCall::abi_encode_returns(&value));
|
||||
}
|
||||
|
||||
/// Execute the balance_of call.
|
||||
fn balance_of(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
call: &IERC20::balanceOfCall,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::balance())?;
|
||||
let account = call.account.into_array().into();
|
||||
let account = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&account);
|
||||
let value =
|
||||
Self::to_u256(pezpallet_assets::Pallet::<Runtime, Instance>::balance(asset_id, account))?;
|
||||
return Ok(IERC20::balanceOfCall::abi_encode_returns(&value));
|
||||
}
|
||||
|
||||
/// Execute the allowance call.
|
||||
fn allowance(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
call: &IERC20::allowanceCall,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::allowance())?;
|
||||
use pezframe_support::traits::fungibles::approvals::Inspect;
|
||||
let owner = call.owner.into_array().into();
|
||||
let owner = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&owner);
|
||||
|
||||
let spender = call.spender.into_array().into();
|
||||
let spender = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&spender);
|
||||
let value = Self::to_u256(pezpallet_assets::Pallet::<Runtime, Instance>::allowance(
|
||||
asset_id, &owner, &spender,
|
||||
))?;
|
||||
|
||||
return Ok(IERC20::balanceOfCall::abi_encode_returns(&value));
|
||||
}
|
||||
|
||||
/// Execute the approve call.
|
||||
fn approve(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
call: &IERC20::approveCall,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::approve_transfer())?;
|
||||
let owner = Self::caller(env)?;
|
||||
let spender = call.spender.into_array().into();
|
||||
let spender = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&spender);
|
||||
|
||||
pezpallet_assets::Pallet::<Runtime, Instance>::do_approve_transfer(
|
||||
asset_id,
|
||||
&<Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&owner),
|
||||
&spender,
|
||||
Self::to_balance(call.value)?,
|
||||
)?;
|
||||
|
||||
Self::deposit_event(
|
||||
env,
|
||||
IERC20Events::Approval(IERC20::Approval {
|
||||
owner: owner.0.into(),
|
||||
spender: call.spender,
|
||||
value: call.value,
|
||||
}),
|
||||
)?;
|
||||
|
||||
return Ok(IERC20::approveCall::abi_encode_returns(&true));
|
||||
}
|
||||
|
||||
/// Execute the transfer_from call.
|
||||
fn transfer_from(
|
||||
asset_id: <Runtime as Config<Instance>>::AssetId,
|
||||
call: &IERC20::transferFromCall,
|
||||
env: &mut impl Ext<T = Runtime>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
env.charge(<Runtime as Config<Instance>>::WeightInfo::transfer_approved())?;
|
||||
let spender = Self::caller(env)?;
|
||||
let spender = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&spender);
|
||||
|
||||
let from = call.from.into_array().into();
|
||||
let from = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&from);
|
||||
|
||||
let to = call.to.into_array().into();
|
||||
let to = <Runtime as pezpallet_revive::Config>::AddressMapper::to_account_id(&to);
|
||||
|
||||
pezpallet_assets::Pallet::<Runtime, Instance>::do_transfer_approved(
|
||||
asset_id,
|
||||
&from,
|
||||
&spender,
|
||||
&to,
|
||||
Self::to_balance(call.value)?,
|
||||
)?;
|
||||
|
||||
Self::deposit_event(
|
||||
env,
|
||||
IERC20Events::Transfer(IERC20::Transfer {
|
||||
from: call.from,
|
||||
to: call.to,
|
||||
value: call.value,
|
||||
}),
|
||||
)?;
|
||||
|
||||
return Ok(IERC20::transferFromCall::abi_encode_returns(&true));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user