1. 引言
在Solana中,智能合約稱為program,
相關代碼見:
- https://github.com/ironaddicteddog/anchor-escrow(Escrow program implemented in Anchor)
- https://github.com/paul-schaaf/solana-escrow
- https://github.com/mvines/solana-bpf-program-template
通過界面創建Solana SPL token有:
- Solana SPL TOKEN CREATOR UI
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中,這些executableaccount 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,
}

3. Solana的token program
前序博客有:
- solana token合約
回到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. 托管合約示例
具體參見:
- https://github.com/paul-schaaf/solana-escrow/scripts【以此為例】
- https://github.com/paul-schaaf/escrow-ui
客戶端1:
$ npm run setup-validator ../program/target/deploy/solana_escrow.so
客戶端2:
$ npm run all
> escrow-scripts@1.0.0 all
> npm run compile && node build/setup.js && node build/alice.js && node build/bob.js
> escrow-scripts@1.0.0 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 │
├─────────┼───────────────────────┼───────────────────────┼─────────────────────┼─────────────────────┤
│ 0 │ 50 │ 0 │ 0 │ 50 │
└─────────┴───────────────────────┴───────────────────────┴─────────────────────┴─────────────────────┘
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 │
├─────────┼───────────────────────┼───────────────────────┼─────────────────────┼─────────────────────┤
│ 0 │ 45 │ 3 │ 5 │ 47 │
└─────────┴───────────────────────┴───────────────────────┴─────────────────────┴─────────────────────┘
參考資料
[1] Programming on Solana - An Introduction
[2] Solana transactions
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/376280.html
標籤:區塊鏈
