diff --git a/pallets/erc20/src/lib.rs b/pallets/erc20/src/lib.rs index cdc37a064..bd2cfee32 100644 --- a/pallets/erc20/src/lib.rs +++ b/pallets/erc20/src/lib.rs @@ -3,71 +3,70 @@ #![cfg_attr(not(feature = "std"), no_std)] use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, + pallet_prelude::*, dispatch::DispatchResult, ensure, traits::{Currency, EnsureOrigin, ExistenceRequirement::AllowDeath, Get}, }; -use frame_system::{self as system, ensure_signed}; +use frame_system::{ensure_signed, pallet_prelude::*}; use pallet_chainbridge as bridge; use pallet_erc721 as erc721; +pub use pallet::*; use sp_arithmetic::traits::SaturatedConversion; use sp_core::U256; use sp_std::prelude::*; type ResourceId = bridge::ResourceId; -type BalanceOf = +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -pub trait Config: system::Config + bridge::Config + erc721::Config { - type RuntimeEvent: From> + Into<::RuntimeEvent>; - /// Specifies the origin check provided by the bridge for calls that can only be called by the - /// bridge pallet - type BridgeOrigin: EnsureOrigin; - - /// The currency mechanism. - type Currency: Currency; - - /// Ids can be defined by the runtime and passed in, perhaps from blake2b_128 hashes. - type HashId: Get; - type NativeTokenId: Get; - type Erc721Id: Get; -} +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + bridge::Config + erc721::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// Specifies the origin check provided by the bridge for calls that can only be called by the + /// bridge pallet + type BridgeOrigin: EnsureOrigin; + + /// The currency mechanism. + type Currency: Currency; + + /// Ids can be defined by the runtime and passed in, perhaps from blake2b_128 hashes. + type HashId: Get; + type NativeTokenId: Get; + type Erc721Id: Get; + } -decl_error! { - pub enum Error for Module{ + #[pallet::error] + pub enum Error { InvalidTransfer, } -} -decl_storage! { - trait Store for Module as Test {} -} - -decl_event!( - pub enum Event where - ::Hash, - { - Remark(Hash), + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + Remark(::Hash), } -); - -decl_module! { - pub struct Module for enum Call where origin: T::RuntimeOrigin { - const HashId: ResourceId = T::HashId::get(); - const NativeTokenId: ResourceId = T::NativeTokenId::get(); - const Erc721Id: ResourceId = T::Erc721Id::get(); - - fn deposit_event() = default; + #[pallet::call] + impl Pallet { // // Initiation calls. These start a bridge transfer. // /// Transfers an arbitrary hash to a (whitelisted) destination chain. - #[weight = 195_000_000] - pub fn transfer_hash(origin, hash: T::Hash, dest_id: bridge::ChainId) -> DispatchResult { + #[pallet::call_index(0)] + #[pallet::weight(195_000_000)] + pub fn transfer_hash(origin: OriginFor, hash: T::Hash, dest_id: bridge::ChainId) -> DispatchResult { ensure_signed(origin)?; let resource_id = T::HashId::get(); @@ -76,8 +75,9 @@ decl_module! { } /// Transfers some amount of the native token to some recipient on a (whitelisted) destination chain. - #[weight = 195_000_000] - pub fn transfer_native(origin, amount: BalanceOf, recipient: Vec, dest_id: bridge::ChainId) -> DispatchResult { + #[pallet::call_index(1)] + #[pallet::weight(195_000_000)] + pub fn transfer_native(origin: OriginFor, amount: BalanceOf, recipient: Vec, dest_id: bridge::ChainId) -> DispatchResult { let source = ensure_signed(origin)?; ensure!(>::chain_whitelisted(dest_id), Error::::InvalidTransfer); let bridge_id = >::account_id(); @@ -91,8 +91,9 @@ decl_module! { /// Transfer a non-fungible token (erc721) to a (whitelisted) destination chain. - #[weight = 195_000_000] - pub fn transfer_erc721(origin, recipient: Vec, token_id: U256, dest_id: bridge::ChainId) -> DispatchResult { + #[pallet::call_index(2)] + #[pallet::weight(195_000_000)] + pub fn transfer_erc721(origin: OriginFor, recipient: Vec, token_id: U256, dest_id: bridge::ChainId) -> DispatchResult { let source = ensure_signed(origin)?; ensure!(>::chain_whitelisted(dest_id), Error::::InvalidTransfer); match >::tokens(token_id) { @@ -112,24 +113,27 @@ decl_module! { // /// Executes a simple currency transfer using the bridge account as the source - #[weight = 195_000_000] - pub fn transfer(origin, to: T::AccountId, amount: BalanceOf) -> DispatchResult { + #[pallet::call_index(3)] + #[pallet::weight(195_000_000)] + pub fn transfer(origin: OriginFor, to: T::AccountId, amount: BalanceOf) -> DispatchResult { let source = T::BridgeOrigin::ensure_origin(origin)?; ::Currency::transfer(&source, &to, amount, AllowDeath)?; Ok(()) } /// This can be called by the bridge to demonstrate an arbitrary call from a proposal. - #[weight = 195_000_000] - pub fn remark(origin, hash: T::Hash) -> DispatchResult { + #[pallet::call_index(4)] + #[pallet::weight(195_000_000)] + pub fn remark(origin: OriginFor, hash: T::Hash) -> DispatchResult { T::BridgeOrigin::ensure_origin(origin)?; - Self::deposit_event(RawEvent::Remark(hash)); + Self::deposit_event(Event::::Remark(hash)); Ok(()) } /// Allows the bridge to issue new erc721 tokens - #[weight = 195_000_000] - pub fn mint_erc721(origin, recipient: T::AccountId, id: U256, metadata: Vec) -> DispatchResult { + #[pallet::call_index(5)] + #[pallet::weight(195_000_000)] + pub fn mint_erc721(origin: OriginFor, recipient: T::AccountId, id: U256, metadata: Vec) -> DispatchResult { T::BridgeOrigin::ensure_origin(origin)?; >::mint_token(recipient, id, metadata)?; Ok(()) diff --git a/pallets/erc721/src/lib.rs b/pallets/erc721/src/lib.rs index 638dc864a..54b6d687c 100644 --- a/pallets/erc721/src/lib.rs +++ b/pallets/erc721/src/lib.rs @@ -4,14 +4,19 @@ use codec::{Decode, Encode}; use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure, + pallet_prelude::*, + dispatch::DispatchResult, ensure, traits::Get, + pallet_prelude::ValueQuery, }; -use frame_system::{self as system, ensure_root, ensure_signed}; +use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; use sp_core::U256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; +pub use pallet::*; + + mod mock; mod tests; @@ -23,17 +28,49 @@ pub struct Erc721Token { pub metadata: Vec, } -pub trait Config: system::Config { - type RuntimeEvent: From> + Into<::RuntimeEvent>; - - /// Some identifier for this token type, possibly the originating ethereum address. - /// This is not explicitly used for anything, but may reflect the bridge's notion of resource - /// ID. - type Identifier: Get<[u8; 32]>; -} +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Some identifier for this token type, possibly the originating ethereum address. + /// This is not explicitly used for anything, but may reflect the bridge's notion of resource + /// ID. + type Identifier: Get<[u8; 32]>; + } -decl_error! { - pub enum Error for Module { + /// Maps tokenId to Erc721 object + #[pallet::storage] + #[pallet::getter(fn tokens)] + pub type Tokens = + StorageMap<_, Blake2_128Concat, TokenId, Erc721Token>; + + /// Maps tokenId to owner + #[pallet::storage] + #[pallet::getter(fn owner_of)] + pub type TokenOwner = + StorageMap<_, Blake2_128Concat, TokenId, T::AccountId>; + + #[pallet::type_value] + pub fn DefaultTokenCount() -> U256 { + U256::zero() + } + + #[pallet::storage] + #[pallet::getter(fn token_count)] + pub type TokenCount = + StorageValue>; + + #[pallet::error] + pub enum Error { /// ID not recognized TokenIdDoesNotExist, /// Already exists with an owner @@ -41,41 +78,24 @@ decl_error! { /// Origin is not owner NotOwner, } -} -decl_storage! { - trait Store for Module as TokenStorage { - /// Maps tokenId to Erc721 object - Tokens get(fn tokens): map hasher(opaque_blake2_256) TokenId => Option; - /// Maps tokenId to owner - TokenOwner get(fn owner_of): map hasher(opaque_blake2_256) TokenId => Option; - /// Total number of tokens in existence - TokenCount get(fn token_count): U256 = U256::zero(); - } -} - -decl_event!( - pub enum Event - where - ::AccountId, - { + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { /// New token created - Minted(AccountId, TokenId), + Minted(T::AccountId, TokenId), /// Token transfer between two parties - Transferred(AccountId, AccountId, TokenId), + Transferred(T::AccountId, T::AccountId, TokenId), /// Token removed from the system Burned(TokenId), } -); - -decl_module! { - pub struct Module for enum Call where origin: T::RuntimeOrigin { - type Error = Error; - fn deposit_event() = default; + #[pallet::call] + impl Pallet { /// Creates a new token with the given token ID and metadata, and gives ownership to owner - #[weight = 195_000_000] - pub fn mint(origin, owner: T::AccountId, id: TokenId, metadata: Vec) -> DispatchResult { + #[pallet::call_index(0)] + #[pallet::weight(195_000_000)] + pub fn mint(origin: OriginFor, owner: T::AccountId, id: TokenId, metadata: Vec) -> DispatchResult { ensure_root(origin)?; Self::mint_token(owner, id, metadata)?; @@ -84,8 +104,9 @@ decl_module! { } /// Changes ownership of a token sender owns - #[weight = 195_000_000] - pub fn transfer(origin, to: T::AccountId, id: TokenId) -> DispatchResult { + #[pallet::call_index(1)] + #[pallet::weight(195_000_000)] + pub fn transfer(origin: OriginFor, to: T::AccountId, id: TokenId) -> DispatchResult { let sender = ensure_signed(origin)?; Self::transfer_from(sender, to, id)?; @@ -94,8 +115,9 @@ decl_module! { } /// Remove token from the system - #[weight = 195_000_000] - pub fn burn(origin, id: TokenId) -> DispatchResult { + #[pallet::call_index(2)] + #[pallet::weight(195_000_000)] + pub fn burn(origin: OriginFor, id: TokenId) -> DispatchResult { ensure_root(origin)?; let owner = Self::owner_of(id).ok_or(Error::::TokenIdDoesNotExist)?; @@ -105,50 +127,50 @@ decl_module! { Ok(()) } } -} - -impl Module { - /// Creates a new token in the system. - pub fn mint_token(owner: T::AccountId, id: TokenId, metadata: Vec) -> DispatchResult { - ensure!(!Tokens::contains_key(id), Error::::TokenAlreadyExists); - - let new_token = Erc721Token { id, metadata }; - - ::insert(id, new_token); - >::insert(id, owner.clone()); - let new_total = ::get().saturating_add(U256::one()); - ::put(new_total); - - Self::deposit_event(RawEvent::Minted(owner, id)); - - Ok(()) - } - - /// Modifies ownership of a token - pub fn transfer_from(from: T::AccountId, to: T::AccountId, id: TokenId) -> DispatchResult { - // Check from is owner and token exists - let owner = Self::owner_of(id).ok_or(Error::::TokenIdDoesNotExist)?; - ensure!(owner == from, Error::::NotOwner); - // Update owner - >::insert(id, to.clone()); - - Self::deposit_event(RawEvent::Transferred(from, to, id)); - - Ok(()) - } - /// Deletes a token from the system. - pub fn burn_token(from: T::AccountId, id: TokenId) -> DispatchResult { - let owner = Self::owner_of(id).ok_or(Error::::TokenIdDoesNotExist)?; - ensure!(owner == from, Error::::NotOwner); - - ::remove(id); - >::remove(id); - let new_total = ::get().saturating_sub(U256::one()); - ::put(new_total); - - Self::deposit_event(RawEvent::Burned(id)); - - Ok(()) - } + impl Pallet { + /// Creates a new token in the system. + pub fn mint_token(owner: T::AccountId, id: TokenId, metadata: Vec) -> DispatchResult { + ensure!(!Tokens::::contains_key(id), Error::::TokenAlreadyExists); + + let new_token = Erc721Token { id, metadata }; + + >::insert(id, new_token); + >::insert(id, owner.clone()); + let new_total = >::get().saturating_add(U256::one()); + >::put(new_total); + + Self::deposit_event(Event::Minted(owner, id)); + + Ok(()) + } + + /// Modifies ownership of a token + pub fn transfer_from(from: T::AccountId, to: T::AccountId, id: TokenId) -> DispatchResult { + // Check from is owner and token exists + let owner = Self::owner_of(id).ok_or(Error::::TokenIdDoesNotExist)?; + ensure!(owner == from, Error::::NotOwner); + // Update owner + >::insert(id, to.clone()); + + Self::deposit_event(Event::Transferred(from, to, id)); + + Ok(()) + } + + /// Deletes a token from the system. + pub fn burn_token(from: T::AccountId, id: TokenId) -> DispatchResult { + let owner = Self::owner_of(id).ok_or(Error::::TokenIdDoesNotExist)?; + ensure!(owner == from, Error::::NotOwner); + + >::remove(id); + >::remove(id); + let new_total = >::get().saturating_sub(U256::one()); + >::put(new_total); + + Self::deposit_event(Event::Burned(id)); + + Ok(()) + } + } } diff --git a/pallets/erc721/src/tests.rs b/pallets/erc721/src/tests.rs index 2a2add321..e4bfb0ca0 100644 --- a/pallets/erc721/src/tests.rs +++ b/pallets/erc721/src/tests.rs @@ -40,12 +40,12 @@ fn mint_burn_tokens() { assert_ok!(Erc721::burn(RuntimeOrigin::root(), id_a)); assert_eq!(Erc721::token_count(), 1.into()); - assert!(!::contains_key(id_a)); + assert!(!>::contains_key(id_a)); assert!(!>::contains_key(id_a)); assert_ok!(Erc721::burn(RuntimeOrigin::root(), id_b)); assert_eq!(Erc721::token_count(), 0.into()); - assert!(!::contains_key(id_b)); + assert!(!>::contains_key(id_b)); assert!(!>::contains_key(id_b)); }) }