Solana中的托管合约——资产交换

1. 引言

在Solana中,智能合约称为program。

相关代码见:

通过界面创建Solana SPL token有:

2. 何为托管合约?

假设Alice有资产X,Bob有资产Y,二者想进行资产交换。
传统的方案为:引入Alice和Bob都信任的第三方Cathy。Cathy只有等收到 Alice发来的X资产 和 Bob发来的Y资产 之后,才会 将Y资产发给Alice 并 将X资产发给Bob。

可通过智能合约来替代可信第三方Cathy的角色。

Solana中的合约为无状态(Stateless)的,若想存储state,需借助accounts参数:

entrypoint!(process_instruction);
fn process_instruction(
    program_id: &Pubkey, //当前执行的合约
    accounts: &[AccountInfo], // The accounts referenced by an instruction represent on-chain state and serve as both the inputs and outputs of a program
    instruction_data: &[u8], // 传给合约的参数
) -> ProgramResult {
    
    
    Processor::process(program_id, accounts, instruction_data)
}

Solana合约本身存储在标记为executable的account中。每个account可hold data and SOL。每个account有一个owner,仅owner可debit the account and adjust its data。Crediting may be done by anyone。

理论上,合约对其拥有的账户拥有完全的自主权。由合约的创建者来限制这种自主权,由合约的用户来验证程序的创建者是否真的这样做了。
所有需要read或write的accounts都必须传入entrypoint function。因为runtime知道所有要读写的account,因此可支持交易并行执行。

Solana中的合约要点为:

  • 每个合约都由其BPF Loader来处理。(合约存储在标记为executable的account中,这些executable account owned by the BPF Loader。)不同的BPF loader可能需要不同的entrypoints。BPF loader本身也是program。【不归BPF Loader所有的合约有:BPF loader本身 以及 System Program。】
  • accounts用于存储state。
  • accounts归属于programs。
  • 只有account owner才可debit an account and adjust its data。
  • 所有读写accounts都需要传入entrypoint中。
  • 不同于以太坊,Solana中同一用户main account账下不同token具有不同的token account。

Solana普通account属性有:

// 普通account属性
pub struct AccountInfo<'a> {
    
    
    pub key: &'a Pubkey,
    pub is_signer: bool,
    pub is_writable: bool,
    pub lamports: Rc<RefCell<&'a mut u64>>,
    pub data: Rc<RefCell<&'a mut [u8]>>, // 仅用于存储user space information。
    pub owner: &'a Pubkey,
    pub executable: bool,
    pub rent_epoch: Epoch,
}

在这里插入图片描述

扫描二维码关注公众号,回复: 13499005 查看本文章

3. Solana的token program

前序博客有:

回到Alice和Bob资产交换的场景,要求Alice和Bob必须有token X的account和token Y的account。
在这里插入图片描述

3.1 token ownership

如何将Alice的main account与其多个token accounts进行关联呢?
Solana token program采用的方案是,Alice对其所有token accounts共用一个private key,为每个token account分配owner。

注意token account的owner 与 普通account owner 的属性不同:

  • 普通account owner 为Solana内部属性,通常普通account owner为a program。
  • token account owner属性有token program在其user space中声明。

在token account的data中,包含了token account的各种属性

  • token account owner属性
  • token account拥有的token数额等等。
// token account属性
pub struct Account {
    
    
    /// The mint associated with this account
    pub mint: Pubkey, // 表示该token account对应哪种token。
    /// The owner of this account.
    pub owner: Pubkey,
    /// The amount of tokens this account holds.
    pub amount: u64,
    /// If `delegate` is `Some` then `delegated_amount` represents
    /// the amount authorized by the delegate
    pub delegate: COption<Pubkey>,
    /// The account's state
    pub state: AccountState,
    /// If is_some, this is a native token, and the value logs the rent-exempt reserve. An Account
    /// is required to be rent-exempt, so the value is used by the Processor to ensure that wrapped
    /// SOL accounts do not drop below this threshold.
    pub is_native: COption<u64>,
    /// The amount delegated
    pub delegated_amount: u64,
    /// Optional authority to close the account.
    pub close_authority: COption<Pubkey>,
}

一旦token account建立完毕,其private key将不再有任何用处,仅其token owner属性有用。
在本例中,token owner属性分别为Alice和Bob的main account。
当需要进行token transfer时,仅需要使用其main account的私钥对tx进行签名即可。

在这里插入图片描述

3.2 transferring ownership

在3.1,通过将token account的owner设置为main account,实现了token account与main account的关联。
接下来,需要考虑的是Alice如何将token transfer 到 escrow合约?

详细可参看 Solana中的跨合约调用 及 Program Derived Addresses 第3节中的Program Derived Addresses(PDAs)技术。

4. 托管合约示例

具体参见:

客户端1:

$ npm run setup-validator ../program/target/deploy/solana_escrow.so

客户端2:

$ npm run all

> [email protected] all
> npm run compile && node build/setup.js && node build/alice.js && node build/bob.js


> [email protected] compile
> tsc -p ./tsconfig.json

Requesting SOL for Alice...
Requesting SOL for Bob...
Requesting SOL for Client...
Creating Mint X...
Creating Alice TokenAccount for X...
Creating Bob TokenAccount for X...
Sending 50X to Alice's X TokenAccount...
Creating Mint Y...
Creating Alice TokenAccount for Y...
Creating Bob TokenAccount for Y...
Sending 50Y to Bob's Y TokenAccount...
✨Setup complete✨

┌─────────┬───────────────────────┬───────────────────────┬─────────────────────┬─────────────────────┐
│ (index) │ Alice Token Account X │ Alice Token Account Y │ Bob Token Account X │ Bob Token Account Y │
├─────────┼───────────────────────┼───────────────────────┼─────────────────────┼─────────────────────┤
│    0500050          │
└─────────┴───────────────────────┴───────────────────────┴─────────────────────┴─────────────────────┘

Sending Alice's transaction...
✨Escrow successfully initialized. Alice is offering 5X for 3Y✨

┌─────────┬───────────────────────┬───────────────────────┬─────────────────────┬─────────────────────┬───────────────────────────┐
│ (index) │ Alice Token Account X │ Alice Token Account Y │ Bob Token Account X │ Bob Token Account Y │ Temporary Token Account X │
├─────────┼───────────────────────┼───────────────────────┼─────────────────────┼─────────────────────┼───────────────────────────┤
│    0    │          45           │           0           │          0          │         50          │             5             │
└─────────┴───────────────────────┴───────────────────────┴─────────────────────┴─────────────────────┴───────────────────────────┘

Sending Bob's transaction...
✨Trade successfully executed. All temporary accounts closed✨

┌─────────┬───────────────────────┬───────────────────────┬─────────────────────┬─────────────────────┐
│ (index) │ Alice Token Account X │ Alice Token Account Y │ Bob Token Account X │ Bob Token Account Y │
├─────────┼───────────────────────┼───────────────────────┼─────────────────────┼─────────────────────┤
│    0453547          │
└─────────┴───────────────────────┴───────────────────────┴─────────────────────┴─────────────────────┘

参考资料

[1] Programming on Solana - An Introduction
[2] Solana transactions

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/121774693