4 个稳定版本

1.0.3 2022 年 12 月 8 日

#256#account

MIT/Apache

10KB
94 代码行

Zipper:抗 rug & 抗 sandwich 原语

交易模拟可能被欺骗;在执行交易时,可能会有一个与预期结果一致的准确模拟,但在实际执行时观察到的结果却不同。

在 Solana 上,交易由多个指令组成。如果交易中的任何指令失败,整个交易就会失败。Zipper 就利用了这一点。

Zipper 是一个链上程序,只包含一条指令。该指令期望一组系统账户和代币账户,以及一组预期余额。如果 SOL 账户或代币账户中的余额不是 至少 提供的预期余额,程序就会崩溃,交易就会失败。

可以在任何修改 SOL 或代币账户的指令之后包含此指令,以确保该指令不会占用比预期更多的 lamports。请注意,只有包含在交易中并标记为可变性的账户需要包含在内。由于这些账户已经包含在您的交易中,所以 Zipper 程序是唯一需要的额外账户。此外,使用有序的 u64 数组来表示预期余额,每个要检查的账户仅增加 8 字节。

示例用法

use anchor_client::{
    solana_sdk::instruction::Instruction,
    Client, Cluster, Program
};
use zipper::{AccountZipper, ID as ZIPPER_PROGRAM_ID};

// A sketchy ix that needs mutable access to user
// token accounts, for whatever reason
let sketchy_ix: Instruction = construct_sketchy_ix(/* todo */);

// Construct a zipper instruction
let client: Client::new_with_options(
        Cluster::Mainnet,
        Rc::new(todo!("keypair")),
        CommitmentConfig::processed(),
    );
let program: Program = client.program(ZIPPER_PROGRAM_ID);
let zipper_ix: Instruction = program.request()
    .accounts(AccountZipper::zip_accounts(&[
            user.keypair.pubkey(),
            user.ata,
            user.ata2,
        ]))
    .args(zipper::instruction::Verify {
        balances: todo!(),
    })
    .instructions()
    .unwrap()
    .remove(0);

// Zip the sketchy instruction with the zipper instruction
let zipped_transaction = Transaction::new_signed_with_payer(
        &[sketchy_ix, zipper_ix],
        Some(&user.keypair.pubkey()),
        &[&*user.keypair],
        get_recent_blockhash(/* todo */),
    );

// If the balances drop under the specified `balances`
// this transaction will fail
send_transaction(&zipped_transaction)

请参阅 rust spoof 测试中的端到端示例,该测试在测试网上进行。

公钥

测试网和主网的程序 ID 为 Z1PrGTgZp5Q1WKewjF4XaTW2nHvNxvbxs7qW8p9qz5U

依赖关系

~11–21MB
~290K SLoC