Deposit and Withdraw

Icon Link存款和取款

考虑以下合约:

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);