考虑以下合约:
contract;
use std::{asset::{mint_to, transfer,}, call_frames::{msg_asset_id,}, context::msg_amount,};
use std::constants::ZERO_B256;
abi LiquidityPool {
#[payable]
fn deposit(recipient: Address);
#[payable]
fn withdraw(recipient: Address);
}
configurable {
TOKEN: AssetId = AssetId::from(0x0000000000000000000000000000000000000000000000000000000000000000),
}
impl LiquidityPool for Contract {
#[payable]
fn deposit(recipient: Address) {
assert(TOKEN == msg_asset_id());
assert(0 < msg_amount());
// Mint two times the amount.
let amount_to_mint = msg_amount() * 2;
// Mint some LP token based upon the amount of the base token.
mint_to(Identity::Address(recipient), ZERO_B256, amount_to_mint);
}
#[payable]
fn withdraw(recipient: Address) {
assert(0 < msg_amount());
// Amount to withdraw.
let amount_to_transfer = msg_amount() / 2;
// Transfer base token to recipient.
transfer(Identity::Address(recipient), TOKEN, amount_to_transfer);
}
}
顾名思义,这个合约代表了一个简化版本的流动性池。deposit()
方法允许您提供任意数量的 BASE_TOKEN
。作为回应,它会将流动性资产的两倍数量铸造到调用者的地址。同样,withdraw()
方法将 BASE_TOKEN
的一半数量转移回调用者的地址。
现在,让我们将一些代币存入流动性池合约中。由于这需要将资产转发到合约,我们需要在创建合约调用时将适当的值传递给 callParams
。
const depositAmount = 100_000;
const liquidityOwner = Wallet.generate({ provider });
// the subId used to mint the new asset is a zero b256 on the contract
const subId = ZeroBytes32;
const contractId = liquidityPoolContract.id.toB256();
const assetId = getMintedAssetId(contractId, subId);
await liquidityPoolContract.functions
.deposit({ bits: liquidityOwner.address.toB256() })
.callParams({ forward: [depositAmount, baseAssetId] })
.txParams({ variableOutputs: 1 })
.call();
const liquidityAmount = await liquidityOwner.getBalance(assetId);
expect(liquidityAmount.toNumber()).toBe(depositAmount * 2);
作为最后的演示,让我们使用所有的流动性资产余额从池中取款,并确认我们收回了初始数量。为此,我们获取流动性资产的余额,并通过 callParams
将其提供给 withdraw()
函数。
await liquidityPoolContract.functions
.withdraw({ bits: liquidityOwner.address.toB256() })
.callParams({ forward: [depositAmount, baseAssetId] })
.txParams({ variableOutputs: 1 })
.call();
const baseAssetAfterWithdraw = await liquidityOwner.getBalance(baseAssetId);
expect(baseAssetAfterWithdraw.toNumber()).toBe(depositAmount / 2);