5- dApps Staking Chain Extension
Prerequisites
Cargo contract installed: https://polkaverse.com/9768/technical-guide-install-cargo-contract-37738
At least on the following node is ready :
- swanky node: https://github.com/AstarNetwork/swanky-node/releases
- substrate contract node: https://github.com/paritytech/substrate-contracts-node/releases
This tutorial uses Ubuntu 22.04, cargo 1.68, cargo contract 2.0 and swanky node
Create the project
You can use the command “cargo contract new” to create a new contract based on the template “flipper“.
cargo contract new dapps_staking_contract
Use dapps staking extension
Add dapps_staking_extension
in your Cargo.toml
and to the std
features
dapps_staking_extension = { git = "https://github.com/swanky-dapps/chain-extension-contracts", default-features = false }
[features]
default = ["std"]
std = [
"ink_metadata/std",
"ink/std",
"scale/std",
"scale-info/std",
"dapps_staking_extension/std"
]
Add use statement in your contract module
pub mod dapp_staking_contract_example{
use dapps_staking_extension::*;
...
Use struct functions directly in your contract
DappsStaking::read_unbonding_period()
DappsStaking::bond_and_stake(...)
DappsStaking::unbond_and_unstake()
Important: In the following statement
#[ink(message, payable)]
pub fn bond_and_stake(&mut self) -> Result<(), DSError> {
// make sure the caller is recorded as staker
let contract = self.env().account_id();
let value = self.env().transferred_value();
DappsStaking::bond_and_stake(contract, value)
}
The tokens are tranferred from caller’s address to the contract’s address and the tokens are locked in the contract’s address. It means, in the dAppStaking module, the staker is the contract and not the caller. It’s why the contract must register the caller as staker.
Register the caller as staker
In the storage, save the amount staked by stakers
#[ink(storage)]
pub struct DAppsStakingContract {
stakers: Mapping<AccountId, Balance>,
}
Save the staked amount before calling the method DappsStaking::bond_and_stake
let caller = self.env().caller();
let value = self.env().transferred_value();
// compute the new stake
let new_stake = match self.stakers.get(&caller){
Some(existing) => {existing.checked_add(value).ok_or(ContractError::AddOverFlow)?}
_ => {value}
};
// save the new amount staked by the caller
self.stakers.insert(&caller, &new_stake);
Remove the unstaked amount before calling the method DappsStaking::unbond_and_unstake
let caller = self.env().caller();
// compute the new stake
let new_stake = match self.stakers.get(&caller){
Some(existing) => {existing.checked_sub(value).ok_or(ContractError::SubOverFlow)?}
_ => {value}
};
// save the new amount staked by the caller
if new_stake == 0 {
self.stakers.remove(&caller);
} else {
self.stakers.insert(&caller, &new_stake);
}
Emit the events
Define the following events
/// Event emitted when a value is staked
#[ink(event)]
pub struct Staked {
#[ink(topic)]
account: AccountId,
era: u32,
amount: Balance,
}
/// Event emitted when a value is unstaked
#[ink(event)]
pub struct Unstaked {
#[ink(topic)]
account: AccountId,
era: u32,
amount: Balance,
}
Emit the event after calling the method DappsStaking::bond_and_stake
// get the current era
let era = DappsStaking::read_current_era();
// emmit the event
self.env().emit_event(Staked { account: caller, era, amount: value });
Emit the event after calling the method DappsStaking::unbond_and_unstake
// get the current era
let era = DappsStaking::read_current_era();
// emmit the event
self.env().emit_event(Unstaked { account: caller, era, amount: value });
Build the project
In the directory “dapps_staking_contract“, use the command “cargo contract build” to compile the project.
cargo contract build
Deploy the contract
You can deploy your contract in local node or swanky node or a testnet.
Here we will start a swanky node and use Contracts UI to interact with the contract.
The result in Contracts UI:
Register your contract in the dApps Staking module
Before staking on a contract, this contract must be registered in the module dApps Staking.
We use the menu “Sudo” in “polkadot.js”.
BondAndStake via ContractsUI
And check the data
Conclusion
Here we registered a contract in the module dApps Staking and used the dApps Staking Chain Extension to interact with the module dApps Staking.
This tutorial covers some methods provided by the dApps Staking Chain Extension and you can found the exhaustive list here:
https://github.com/swanky-dapps/chain-extension-contracts/blob/main/crates/dapps-staking/lib.rs
Git repository
https://github.com/GuiGou12358/astar-tutorials/tree/main/tuto5
Source
Crypto-enthusiast, Defi & NFT believer, Dotsam Fam Astar Tech Amb & Phala Amb Web2 builder gradually migrating to Web3
Tutorials to write Smart Contracts in Rust and Ink!
0 comments