-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
601 additions
and
9 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
[package] | ||
name = "dock-cheqd-migration" | ||
version = "0.1.0" | ||
authors = ["Dock.io"] | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies.bech32] | ||
version = "0.11.0" | ||
default-features = false | ||
features = ["alloc"] | ||
|
||
[dev-dependencies.pallet-balances] | ||
default-features = false | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dependencies.scale-info-derive] | ||
git = "https://github.com/docknetwork/scale-info.git" | ||
branch = "master" | ||
|
||
[dependencies.scale-info] | ||
version = "2.1.2" | ||
default-features = false | ||
features = ["derive"] | ||
|
||
[dependencies.codec] | ||
default-features = false | ||
features = ["derive"] | ||
package = "parity-scale-codec" | ||
version = "3.1.5" | ||
|
||
[dependencies.serde] | ||
features = ["derive"] | ||
optional = true | ||
version = "1.0.119" | ||
|
||
[dependencies.frame-support] | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dependencies.frame-system] | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dependencies.sp-std] | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dependencies.frame-benchmarking] | ||
optional = true | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dev-dependencies.sp-io] | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dev-dependencies.sp-core] | ||
default-features = false | ||
# version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[dependencies.sp-runtime] | ||
default-features = false | ||
#version = "3.0.0" | ||
git = "https://github.com/paritytech/substrate.git" | ||
branch = "polkadot-v0.9.29" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"codec/std", | ||
"serde", | ||
"bech32/std", | ||
"frame-support/std", | ||
"frame-system/std", | ||
"pallet-balances/std", | ||
"sp-std/std", | ||
"frame-benchmarking/std", | ||
"sp-runtime/std", | ||
] | ||
test = ["std"] | ||
runtime-benchmarks = ["frame-benchmarking"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
use super::*; | ||
use frame_benchmarking::{benchmarks, whitelisted_caller}; | ||
use frame_support::traits::{Currency, IsType}; | ||
use frame_system::{Pallet as System, RawOrigin}; | ||
use scale_info::prelude::string::ToString; | ||
use sp_runtime::{traits::Zero, DispatchError}; | ||
|
||
fn assert_event<T: Config>(expected_event: impl Into<<T as pallet::Config>::Event>) { | ||
let events = System::<T>::events(); | ||
let expected_event = expected_event.into(); | ||
|
||
assert!(events | ||
.iter() | ||
.any(|event| &event.event == expected_event.into_ref())); | ||
} | ||
|
||
benchmarks! { | ||
migrate { | ||
let destination = "cheqd1fktkf9nsj625jkxz7r7gmryna6uy8y2pptang4".to_string(); | ||
let caller: T::AccountId = whitelisted_caller(); | ||
T::Currency::make_free_balance_be(&caller, 100_000_000u32.into()); | ||
let dock_amount = T::Currency::free_balance(&caller); | ||
|
||
}: _(RawOrigin::Signed(caller.clone()), destination.clone()) | ||
verify { | ||
assert_event::<T>(Event::<T>::Migrated { | ||
sender: caller.clone(), | ||
cheqd_recipient: CheqdAddress::new::<T>(destination).unwrap(), | ||
dock_amount, | ||
}); | ||
assert!( | ||
T::Currency::free_balance(&caller).is_zero() | ||
); | ||
} | ||
|
||
migrate_validation_failure { | ||
let destination = "cosmos12zddgw36trnvwm4s3x0etjd86r4lgqdthrzjdk".to_string(); | ||
let caller: T::AccountId = whitelisted_caller(); | ||
let dock_amount = T::Currency::free_balance(&caller); | ||
|
||
}: { | ||
Pallet::<T>::migrate(RawOrigin::Signed(caller.clone()).into(), destination.clone()).unwrap_err(); | ||
Ok::<_, DispatchError>(()) | ||
} | ||
verify { | ||
assert_eq!( | ||
T::Currency::free_balance(&caller), dock_amount | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
//! A pallet that facilitates the smooth transfer of `DOCK` tokens from the `Dock` Chain to `CHEQD` tokens on the `Cheqd` Chain. | ||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
use scale_info::prelude::string::String; | ||
|
||
#[cfg(feature = "runtime-benchmarks")] | ||
pub mod benchmarks; | ||
#[cfg(test)] | ||
mod mock; | ||
#[cfg(test)] | ||
mod tests; | ||
mod weights; | ||
|
||
// Re-export pallet items so that they can be accessed from the crate namespace. | ||
pub use pallet::*; | ||
|
||
use weights::{SubstrateWeight, WeightInfo}; | ||
|
||
#[frame_support::pallet] | ||
pub mod pallet { | ||
use super::*; | ||
use frame_support::{ | ||
dispatch::WithPostDispatchInfo, | ||
pallet_prelude::*, | ||
traits::{Currency, ExistenceRequirement::AllowDeath}, | ||
}; | ||
use frame_system::pallet_prelude::*; | ||
use sp_runtime::traits::Zero; | ||
|
||
type BalanceOf<T> = | ||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance; | ||
|
||
/// Address of the recipient on the `cheqd` side. | ||
#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] | ||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] | ||
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] | ||
#[derive(scale_info_derive::TypeInfo)] | ||
#[scale_info(omit_prefix)] | ||
pub struct CheqdAddress(String); | ||
|
||
impl CheqdAddress { | ||
pub fn new<T>(value: String) -> Result<Self, Error<T>> { | ||
let (prefix, addr) = | ||
bech32::decode(&value).map_err(|_| Error::<T>::AddressMustBeValidBech32)?; | ||
ensure!( | ||
prefix.as_str() == "cheqd", | ||
Error::<T>::AddressMustStartWithCheqd | ||
); | ||
ensure!(addr.len() == 20, Error::<T>::InvalidAddressLength); | ||
|
||
Ok(Self(value)) | ||
} | ||
} | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config { | ||
/// The overarching event type. | ||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>; | ||
/// The currency to be burnt during migration. | ||
type Currency: Currency<Self::AccountId>; | ||
/// Id of the recipient account on the dock side to send burnt funds. | ||
type BurnDestination: Get<Self::AccountId>; | ||
} | ||
|
||
#[pallet::error] | ||
pub enum Error<T> { | ||
/// `cheqd` address must start with `cheqd` prefix. | ||
AddressMustStartWithCheqd, | ||
/// Provided `cheqd` address is invalid because it has an incorrect length. | ||
InvalidAddressLength, | ||
/// `cheqd` address part coming after `cheqd` must be a valid bech-32 sequence. | ||
AddressMustBeValidBech32, | ||
/// Caller account's balance is zero. | ||
BalanceIsZero, | ||
} | ||
|
||
#[pallet::pallet] | ||
pub struct Pallet<T>(_); | ||
|
||
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
/// Burns the free `DOCK` balance of the sender and emits an event containing the supplied recipient `cheqd` address. | ||
/// By submitting this transaction, you agree to the Terms and Conditions. | ||
#[pallet::weight(SubstrateWeight::<T::DbWeight>::migrate())] | ||
pub fn migrate(origin: OriginFor<T>, cheqd_address: String) -> DispatchResultWithPostInfo { | ||
let sender = ensure_signed(origin)?; | ||
|
||
let cheqd_recipient = CheqdAddress::new::<T>(cheqd_address) | ||
.map_err(DispatchError::from) | ||
.map_err(|error| { | ||
error.with_weight(SubstrateWeight::<T::DbWeight>::migrate_validation_failure()) | ||
})?; | ||
|
||
let dock_amount = T::Currency::free_balance(&sender); | ||
ensure!(!dock_amount.is_zero(), Error::<T>::BalanceIsZero); | ||
|
||
let dest = T::BurnDestination::get(); | ||
T::Currency::transfer(&sender, &dest, dock_amount, AllowDeath)?; | ||
|
||
Self::deposit_event(Event::Migrated { | ||
sender, | ||
cheqd_recipient, | ||
dock_amount, | ||
}); | ||
|
||
Ok(Pays::Yes.into()) | ||
} | ||
} | ||
|
||
#[pallet::event] | ||
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
/// The corresponding amount of `DOCK` tokens was burned on the `Dock` Chain side, and an equivalent amount of `CHEQD` tokens will be issued to the specified address on the `cheqd` Chain side. | ||
/// Terms and conditions were accepted by the sender. | ||
Migrated { | ||
/// The account whose funds were burnt on the `Dock` side. | ||
sender: T::AccountId, | ||
/// Recipient address on the `cheqd` side. | ||
cheqd_recipient: CheqdAddress, | ||
/// Amount of the burnt DOCK tokens. | ||
dock_amount: BalanceOf<T>, | ||
}, | ||
} | ||
} |
Oops, something went wrong.