diff --git a/Cargo.toml b/Cargo.toml index ccfc1ae5..9fa1a3af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,7 @@ members = [ "precompiles/sr25519", "precompiles/utils", "precompiles/xcm", + "chainextensions/traits", + "chainextensions/balances", + "chainextensions/dapps-staking", ] diff --git a/chainextensions/balances/Cargo.toml b/chainextensions/balances/Cargo.toml new file mode 100644 index 00000000..f96af078 --- /dev/null +++ b/chainextensions/balances/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "chain-extension-balances" +version = "4.0.0" +authors = ["Stake Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://astar.network" +repository = "https://github.com/AstarNetwork/astar-frame" +description = "dApps Staking chain extension for WASM contracts" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +num-traits = { version = "0.2", default-features = false } +scale-info = { version = "2.1.0", default-features = false, features = ["derive"] } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +pallet-contracts = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false, features = ["unstable-interface"] } +pallet-contracts-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +pallet-contracts-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +log = "0.4.16" + +# Astar +chain-extension-traits = { path = "../traits", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "num-traits/std", + "pallet-contracts/std", + "pallet-contracts-primitives/std", + "pallet-contracts-rpc-runtime-api/std", + "pallet-balances/std", + "scale-info/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", +] + diff --git a/chainextensions/balances/src/lib.rs b/chainextensions/balances/src/lib.rs new file mode 100644 index 00000000..914fcb7e --- /dev/null +++ b/chainextensions/balances/src/lib.rs @@ -0,0 +1,60 @@ +#![cfg_attr(not(feature = "std"), no_std)] +use chain_extension_traits::ChainExtensionExec; +use codec::Encode; +use frame_support::log::{error, trace}; +use pallet_contracts::chain_extension::{Environment, Ext, InitState, SysConfig, UncheckedFrom}; +use sp_runtime::DispatchError; + +pub struct BalancesExtension; + +impl ChainExtensionExec for BalancesExtension { + fn execute_func(func_id: u32, env: Environment) -> Result<(), DispatchError> + where + E: Ext, + ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, + { + let mut env = env.buf_in_buf_out(); + match func_id { + // Balances - free_balance() + 1 => { + let arg: ::AccountId = env.read_as()?; + let free_balance = pallet_balances::Pallet::::free_balance(arg.clone()); + let free_balance_encoded = free_balance.encode(); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:} free_balance_encoded:{:?}, arg:{:?}", + func_id, + free_balance_encoded, + arg + ); + env.write(&free_balance_encoded, false, None).map_err(|_| { + DispatchError::Other("ChainExtension failed to call free_balance") + })?; + } + // balances - usable_balance() + 2 => { + let arg: ::AccountId = env.read_as()?; + let usable_balance = pallet_balances::Pallet::::usable_balance(arg.clone()); + let usable_balance_encoded = usable_balance.encode(); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:} usable_balance_encoded:{:?}, arg:{:?}", + func_id, + usable_balance_encoded, + arg + ); + env.write(&usable_balance_encoded, false, None) + .map_err(|_| { + DispatchError::Other("ChainExtension failed to call usable_balance") + })?; + } + _ => { + error!("Called an unregistered `func_id`: {:}", func_id); + return Err(DispatchError::Other( + "BalancesExtension: Unimplemented func_id", + )); + } + } + Ok(()) + } +} diff --git a/chainextensions/dapps-staking/Cargo.toml b/chainextensions/dapps-staking/Cargo.toml new file mode 100644 index 00000000..44b83da8 --- /dev/null +++ b/chainextensions/dapps-staking/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-chain-extension-dapps-staking" +version = "4.0.0" +authors = ["Stake Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://astar.network" +repository = "https://github.com/AstarNetwork/astar-frame" +description = "dApps Staking chain extension for WASM contracts" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +num-traits = { version = "0.2", default-features = false } +scale-info = { version = "2.1.0", default-features = false, features = ["derive"] } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +pallet-contracts = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false, features = ["unstable-interface"] } +pallet-contracts-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +pallet-contracts-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } +log = "0.4.16" + +# Astar +chain-extension-traits = { path = "../traits", default-features = false } +pallet-dapps-staking = { path = "../../frame/dapps-staking", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "num-traits/std", + "pallet-contracts/std", + "pallet-contracts-primitives/std", + "pallet-contracts-rpc-runtime-api/std", + "pallet-dapps-staking/std", + "scale-info/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", +] + diff --git a/chainextensions/dapps-staking/src/lib.rs b/chainextensions/dapps-staking/src/lib.rs new file mode 100644 index 00000000..0dc8a5f1 --- /dev/null +++ b/chainextensions/dapps-staking/src/lib.rs @@ -0,0 +1,65 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use chain_extension_traits::ChainExtensionExec; +use codec::Encode; +use frame_support::log::{error, trace}; +use pallet_contracts::chain_extension::{Environment, Ext, InitState, SysConfig, UncheckedFrom}; +use sp_runtime::DispatchError; + +pub struct DappsStakingExtension; + +impl ChainExtensionExec for DappsStakingExtension { + fn execute_func(func_id: u32, env: Environment) -> Result<(), DispatchError> + where + E: Ext, + ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, + { + let mut env = env.buf_in_buf_out(); + match func_id { + // DappsStaking - current_era() + 1 => { + let current_era = pallet_dapps_staking::CurrentEra::::get(); + let current_era_encoded = current_era.encode(); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:} current_era:{:?}", + func_id, + ¤t_era_encoded + ); + + env.write(¤t_era_encoded, false, None).map_err(|_| { + DispatchError::Other( + "ChainExtension DappsStakingExtension failed to write result", + ) + })?; + } + + // DappsStaking - general_era_info() + 2 => { + let arg: u32 = env.read_as()?; + let era_info = pallet_dapps_staking::GeneralEraInfo::::get(arg) + .ok_or(DispatchError::Other("general_era_info call failed")); + let era_info_encoded = era_info.encode(); + trace!( + target: "runtime", + "[ChainExtension]|call|func_id:{:} era_info_encoded:{:?}", + func_id, + &era_info_encoded + ); + + env.write(&era_info_encoded, false, None).map_err(|_| { + DispatchError::Other( + "ChainExtension DappsStakingExtension failed to write result", + ) + })?; + } + _ => { + error!("Called an unregistered `func_id`: {:}", func_id); + return Err(DispatchError::Other( + "DappsStakingExtension: Unimplemented func_id", + )); + } + } + Ok(()) + } +} diff --git a/chainextensions/traits/Cargo.toml b/chainextensions/traits/Cargo.toml new file mode 100644 index 00000000..14260341 --- /dev/null +++ b/chainextensions/traits/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "chain-extension-traits" +version = "4.0.0" +authors = ["Stake Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://astar.network" +repository = "https://github.com/AstarNetwork/astar-frame" +description = "dApps Staking chain extension for WASM contracts" + +[dependencies] +pallet-contracts = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false, features = ["unstable-interface"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } + +[features] +default = ["std"] +std = [ + "pallet-contracts/std", + "sp-runtime/std", +] + diff --git a/chainextensions/traits/src/lib.rs b/chainextensions/traits/src/lib.rs new file mode 100644 index 00000000..cb8015e0 --- /dev/null +++ b/chainextensions/traits/src/lib.rs @@ -0,0 +1,10 @@ +#![cfg_attr(not(feature = "std"), no_std)] +use pallet_contracts::chain_extension::{Environment, Ext, InitState, SysConfig, UncheckedFrom}; +use sp_runtime::DispatchError; + +pub trait ChainExtensionExec { + fn execute_func(func_id: u32, env: Environment) -> Result<(), DispatchError> + where + E: Ext, + ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>; +}