substrate,ink!,solidity,openbrush,patract
impl PSP34 for PositionMangerContract {}
WETH9合约是可以让你的native token 和指定的wrap eth token进行一比一的兑换。在swap中进行native token 和其他token进行互换的时候,可以先把native token 兑换成wraptoken,从而进行swap。 可以先实现weth9的接口。接口实现如下:
use brush::contracts::psp22::PSP22Error;
/// base info for PSP34
#[brush::wrapper]
pub type Weth9Ref = dyn Weth9;
#[brush::trait_definition]
pub trait Weth9 {
/// @notice Deposit ether to get wrapped ether
#[ink(message,payable)]
fn deposit(&mut self)->Result<(),PSP22Error>;
/// @notice Withdraw wrapped ether to get ether
#[ink(message)]
fn withdraw(&mut self,amount:u128)->Result<(),PSP22Error>;
}
首先定义weth9需要使用的接口,deposit是抵押接口,给这个接口转入native token,就可以得到对应的weth9的token。 第二个接口是赎回,使用weth9可以赎回相同数量的native token。 这个trait需要使用#[brush::trait_definition]过程宏进行标记。
定义好接口后,我们就可以实现这个trait了。
use brush::contracts::psp22::{PSP22Storage, PSP22Internal, PSP22Error};
// use brush::traits::Flush;
use ink_env::{DefaultEnvironment};
pub use crate::traits::periphery::weth9::*;
use ink_prelude::string::String;
impl<T: PSP22Storage + PSP22Internal> Weth9 for T {
/// @notice Deposit ether to get wrapped ether
default fn deposit(&mut self)->Result<(),PSP22Error>{
let transfer_value = ink_env::transferred_value::<DefaultEnvironment>();
let caller = ink_env::caller::<DefaultEnvironment>();
let result = PSP22Internal::_mint(self, caller, transfer_value);
result
}
/// @notice Withdraw wrapped ether to get ether
default fn withdraw(&mut self,amount:u128)->Result<(),PSP22Error>{
let caller = ink_env::caller::<DefaultEnvironment>();
let balance = PSP22Internal::_balance_of(self, &caller);
assert!(balance >= amount,"balance not enough!");
PSP22Internal::_burn_from(self, caller, amount)?;
let result = ink_env::transfer::<DefaultEnvironment>(caller, amount);
result.map_err(|_|PSP22Error::Custom(String::from("transfer error!")))
}
}
由于weth9需要进行token的转账,所以T要满足PSP22Storage
和PSP22Internal
这两个trait。
然后对T进行default的实现。这样在真正的weth9的合约中直接继承trait的默认方法。
impl Weth9 for Weth9Contract{}
当然weth9的合约数据要满足PSP22Data
和PSP22MetadataData
的数据结构,从而让合约满足PSP22Storage
的trait。具体代码如下:
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]
/// This is a simple `PSP-22` which will be used as a stable coin and a collateral token in our lending contract
#[brush::contract]
pub mod weth9 {
use brush::contracts::psp22::extensions::metadata::*;
use ink_prelude::string::String;
// use lending_project::traits::stable_coin::*;
use ink_storage::traits::SpreadAllocate;
use crabswap::impls::weth9::*;
/// Define the storage for PSP22 data and Metadata data
#[ink(storage)]
#[derive(Default, SpreadAllocate, PSP22Storage, PSP22MetadataStorage)]
pub struct Weth9Contract {
#[PSP22StorageField]
psp22: PSP22Data,
#[PSP22MetadataStorageField]
metadata: PSP22MetadataData,
}
/// implement PSP22 Trait for our coin
impl PSP22 for Weth9Contract {}
/// implement PSP22Metadata Trait for our coin
impl PSP22Metadata for Weth9Contract {}
impl Weth9 for Weth9Contract{}
// It forces the compiler to check that you implemented all super traits
// impl StableCoin for StableCoinContract {}
impl Weth9Contract {
/// constructor with name and symbol
#[ink(constructor)]
pub fn new(name: Option<String>, symbol: Option<String>) -> Self {
ink_lang::codegen::initialize_contract(|instance: &mut Weth9Contract| {
instance.metadata.name = name;
instance.metadata.symbol = symbol;
instance.metadata.decimals = 12;
let total_supply = 0 * 10_u128.pow(instance.metadata.decimals.into()); //不可手工增发,
assert!(instance._mint(instance.env().caller(), total_supply).is_ok());
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use ink_env::DefaultEnvironment;
use ink_lang as ink;
fn default_accounts(
) -> ink_env::test::DefaultAccounts<ink_env::DefaultEnvironment> {
ink_env::test::default_accounts::<Environment>()
}
fn set_next_caller(caller: AccountId) {
ink_env::test::set_caller::<Environment>(caller);
}
#[ink::test]
fn register_works() {
let default_accounts = default_accounts();
set_next_caller(default_accounts.alice);
let weth9_contract = Weth9Contract::new(Some(String::from("weth9")),Some(String::from("weth91")));
assert_eq!(weth9_contract.metadata.name,Some(String::from("weth9")));
}
#[ink::test]
fn test_deposit() {
let accounts = default_accounts();
set_next_caller(accounts.alice);
let mut weth9_contract = Weth9Contract::new(Some(String::from("weth9")),Some(String::from("weth91")));
ink_env::test::set_value_transferred::<ink_env::DefaultEnvironment>(1000);
assert_eq!(weth9_contract.deposit(),Ok(()));
let balance = weth9_contract.balance_of(accounts.alice);
assert_eq!(balance,1000u128,"balance not correct!");
let contract_account_id = ink_env::test::callee::<ink_env::DefaultEnvironment>();
let native_balance:Balance = ink_env::test::get_account_balance::<ink_env::DefaultEnvironment>(contract_account_id).unwrap();
// assert_eq!(native_balance,1000u128,"native balance not correct!");
}
#[ink::test]
fn test_withdraw() {
let accounts = default_accounts();
set_next_caller(accounts.alice);
let mut weth9_contract = Weth9Contract::new(Some(String::from("weth9")),Some(String::from("weth91")));
ink_env::test::set_value_transferred::<ink_env::DefaultEnvironment>(1000);
assert_eq!(weth9_contract.deposit(),Ok(()));
let balance = weth9_contract.balance_of(accounts.alice);
assert_eq!(balance,1000u128,"balance not correct!");
assert_eq!(weth9_contract.withdraw(800u128),Ok(()));
let balance = weth9_contract.balance_of(accounts.alice);
assert_eq!(balance,1000u128-800u128,"balance not correct!");
}
// #[ink::test]
// fn transfer_works() {
// let accounts = default_accounts();
// let name = Hash::from([0x99; 32]);
// set_next_caller(accounts.alice);
// let mut contract = DomainNameService::new();
// assert_eq!(contract.register(name), Ok(()));
// // Test transfer of owner.
// assert_eq!(contract.transfer(name, accounts.bob), Ok(()));
// // Owner is bob, alice `set_address` should fail.
// assert_eq!(
// contract.set_address(name, accounts.bob),
// Err(Error::CallerIsNotOwner)
// );
// set_next_caller(accounts.bob);
// // Now owner is bob, `set_address` should be successful.
// assert_eq!(contract.set_address(name, accounts.bob), Ok(()));
// assert_eq!(contract.get_address(name), accounts.bob);
// }
}
}
另外大量的libs库可以直接使用rust语言进行编写。 写完合约后可以使用PATRACT公司的redspot的js框架进行测试。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!