I am writing a contract in RUST for staking and unstaking DOT tokens I have used ink , cargo and sustrate to do this . This is my lib.rs :
lib.rs:
#![cfg_attr(not(feature = "std"), no_std)]
#[ink::contract]
mod polkadot_staking_exchange {
use ink::prelude::vec::Vec;
use ink::storage::Mapping;
use scale::{Decode, Encode};
#[derive(Encode, Decode, Clone, Default)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub struct StakeInfo {
amount: u128,
start_time: u64,
is_active: bool,
}
#[derive(Encode, Decode, Clone, Default)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub struct UnstakeRequest {
amount: u128,
request_time: u64,
}
#[ink(storage)]
pub struct PolkadotFlexiStakingExchange {
owner: AccountId,
treasury_address: AccountId,
user_stakes: Mapping<AccountId, Vec<StakeInfo>>,
unstake_requests: Mapping<AccountId, Vec<UnstakeRequest>>,
interest_rate_history: Vec<(u128, u64)>,
cooling_period: u64,
fee_percentage: u128,
}
impl PolkadotFlexiStakingExchange {
#[ink(constructor)]
pub fn new(
owner: AccountId,
treasury_address: AccountId,
cooling_period: u64,
initial_fee_percentage: u128,
) -> Self {
let mut instance = Self {
owner,
treasury_address,
user_stakes: Mapping::default(),
unstake_requests: Mapping::default(),
interest_rate_history: Vec::new(),
cooling_period,
fee_percentage: initial_fee_percentage,
};
instance
.interest_rate_history
.push((50000000000000000, Self::env().block_timestamp()));
instance
}
#[ink(message)]
pub fn set_treasury_address(&mut self, treasury_address: AccountId) {
self.treasury_address = treasury_address;
}
#[ink(message)]
pub fn update_interest_rate(&mut self, new_rate: u128) {
self.interest_rate_history
.push((new_rate, Self::env().block_timestamp()));
}
#[ink(message)]
pub fn stake(&mut self, amount: u128) {
let caller = Self::env().caller();
let value = Self::env().transferred_value(); // Correct method is transferred_value()
assert!(value >= amount, "Insufficient stake amount sent");
let stake_info = StakeInfo {
amount,
start_time: Self::env().block_timestamp(),
is_active: true,
};
let mut stakes = self.user_stakes.get(caller).unwrap_or_default(); // Use get method for Mapping
stakes.push(stake_info);
// Insert or update stakes for the caller
self.user_stakes.insert(caller, &stakes);
}
#[ink(message)]
pub fn request_unstake(&mut self, amount: u128) {
let caller = self.env().caller();
let request = UnstakeRequest {
amount,
request_time: self.env().block_timestamp(),
};
// Retrieve current requests or default to an empty vector
let mut requests = self.unstake_requests.get(caller).unwrap_or_default();
// Push the new unstake request
requests.push(request);
// Insert the updated requests back into the Mapping
self.unstake_requests.insert(caller, &requests);
}
#[ink(message)]
pub fn process_unstake_requests(&mut self) {
let caller = Self::env().caller();
if let Some(requests) = self.unstake_requests.get(caller) {
for request in requests.iter() {
// Use `checked_add` to prevent overflow
let request_time_with_cooling = request
.request_time
.checked_add(self.cooling_period)
.expect("Overflow occurred");
// Assert cooling period has passed
assert!(
self.env().block_timestamp() >= request_time_with_cooling,
"Cooling period has not passed"
);
assert!(
self.env().balance() >= request.amount,
"Contract does not have enough balance"
);
Self::env()
.transfer(caller, request.amount)
.expect("Transfer failed");
}
self.unstake_requests.remove(caller);
}
}
#[ink(message)]
pub fn get_total_staked(&self, user: AccountId) -> u128 {
if let Some(stakes) = self.user_stakes.get(user) {
stakes.iter().map(|s| s.amount).sum()
} else {
0
}
}
#[ink(message)]
pub fn withdraw(&mut self, amount: u128) {
assert!(
Self::env().balance() >= amount,
"Insufficient balance in contract"
);
Self::env()
.transfer(self.owner, amount)
.expect("Withdraw failed");
}
}
}
and this is my Cargo.toml:
[package]
name = "polkadot_staking_exchange"
version = "0.1.0"
edition = "2021"
[dependencies]
ink = { version = "4.0.0-beta", default-features = false }
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true }
[dev-dependencies]
ink_e2e = { path = "../../crates/e2e" }
[lib]
name = "polkadot_staking_exchange"
path = "src/lib.rs"
crate-type = ["cdylib", ]
[features]
default = ["std"]
std = [
"ink/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []
e2e-tests = []
the lib.rs is inside src folder . I keep getting this error when I run cargo contract build “the target polkadot_staking_exchange
is a binary and can’t have any crate-types set (currently “cdylib”)” why?