SOL合约部署调用与销毁

SOL合约部署调用与销毁

常见术语

  • SPL: Solana Program Library
  • PDAs: Program Derived Addresses
  • CPI: Cross-Program Invocation

BPF is a highly efficient bytecode execution environment initially developed for network packet filtering in the Linux kernel. Solana leverages BPF as the execution environment for its smart contracts

开发环境

参考 https://solana.com/developers/guides/getstarted/setup-local-development

由于 devnet 会定时删数据滚服,然后 chain_id+=1 所以用 devnet 好处是数据少 rpc 节点负担小 延迟低

solana config set --url https://api.devnet.solana.com

然后就是 devnet 基础设施多点(explorer区块浏览器也能连localhost),主要是我可怜的笔记本内存太小了不想运行个sol全节点

Anchor framework 应该指的是 sol 的智能合约开发框架

就像eth不用remix这样web的IDE,sol也不用solana playground否则像我当初remix学solidity都是一键傻瓜部署运行结果连部署和调用的底层原理一点都不懂

创建项目

代码在 https://solana.com/developers/guides/getstarted/hello-world-in-your-browser

cargo new --lib firstsol
cd firstsol
echo -e '[toolchain]\nchannel = "1.76.0"\n' > rust-toolchain.toml
cargo add solana-program

[lib]
crate-type = ["cdylib", "lib"]

sol NFT 合约代码可以参考 https://github.com/the-web3/nft-share/blob/main/SolNft/programs/SolNft/src/lib.rs

部署合约

cargo build-bpf 默认就是 release 编译 由于 rent-exempt reserve 机制存在,智能合约so文件体积越小存储费用越低

$ solana program deploy target/deploy/firstsol.so
Program Id: 6jL67XKqEVWPBZEmMT8AuhTP4zJefpPs48BmV3JLxncR

好贵,收了我 0.14 SOL 的 GAS

$ solana program show --programs
Program Id                                   | Slot      | Authority                                    | Balance
6jL67XKqEVWPBZEmMT8AuhTP4zJefpPs48BmV3JLxncR | 312032887 | 6YA5ZxLRNuYEg44xbkLPtgbu5dBQdEftcWS31kpyba4f | 0.1350588 SOL

Authority 列应该就是合约发布者也就是我的钱包地址, 跟ETH的POS类似 一个区块中会有多个Slot 312032887 类似于 slot_id

ts调用合约

并不能像 aptos/sui 那样用命令行工具调用(claude3.5 API会骗你说可以),用 ts/rust 调用会方便点

import {
    Connection,
    PublicKey,
    Keypair,
    Transaction,
    sendAndConfirmTransaction,
    TransactionInstruction
} from '@solana/web3.js';
import * as fs from 'fs';
(async () => {
    const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
    // Read the keypair from the file
    const keypairPath = `${process.env.HOME}/.config/solana/id.json`;
    const keypairData = JSON.parse(fs.readFileSync(keypairPath, 'utf8'));
    const payer = Keypair.fromSecretKey(new Uint8Array(keypairData));
    const programId = new PublicKey('6jL67XKqEVWPBZEmMT8AuhTP4zJefpPs48BmV3JLxncR');

    // Create an instruction to call your program
    const instruction = new TransactionInstruction({
        keys: [{pubkey: payer.publicKey, isSigner: true, isWritable: true}],
        programId,
        data: Buffer.alloc(0)
    });
    // Create a transaction
    const transaction = new Transaction().add(instruction);
    // Sign and Send the transaction
    const signature = await sendAndConfirmTransaction(
        connection,
        transaction,
        [payer]
    );
    console.log('Transaction sent with signature:', signature);
})();

区块浏览器上看看 https://explorer.solana.com/tx/3nFhxCp6hvHCLFmVd3YgkpbrsS9jxBF7Jwy3MNvcSBFG25KZeeNL3xasQEK9msGh3cjy6uJMTUGR2jYX9TZmeXyR?cluster=devnet

w@w:~/solana$ solana confirm -v 3nFhxCp6hvHCLFmVd3YgkpbrsS9jxBF7Jwy3MNvcSBFG25KZeeNL3xasQEK9msGh3cjy6uJMTUGR2jYX9TZmeXyR
RPC URL: https://api.devnet.solana.com
Default Signer Path: /home/w/.config/solana/id.json
Commitment: confirmed

Unknown Program (6jL67XKqEVWPBZEmMT8AuhTP4zJefpPs48BmV3JLxncR): Unknown Instruction
> Program logged: "Hello, world!"
> Program consumed: 340 of 200000 compute units
> Program returned success

或者用 solana cli

solana logs | grep "6jL67XKqEVWPBZEmMT8AuhTP4zJefpPs48BmV3JLxncR invoke" -A3

rs调用合约

use solana_client::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::CommitmentConfig,
    instruction::{AccountMeta, Instruction},
    pubkey::Pubkey,
    signature::Signer,
    transaction::Transaction,
};
fn main() {
    dotenv::dotenv().unwrap();
    let connection = RpcClient::new_with_commitment(
        "https://api.devnet.solana.com".to_string(),
        CommitmentConfig::confirmed(),
    );
    let payer = solana_client_example::keypair();
    let program_id: Pubkey = std::env::var("program_id").unwrap().parse().unwrap();

    let instruction = Instruction {
        program_id,
        accounts: vec![AccountMeta::new(payer.pubkey(), true)],
        data: Vec::new(),
    };
    let transaction = Transaction::new_signed_with_payer(
        &[instruction],
        Some(&payer.pubkey()),
        &[&payer],
        connection.get_latest_blockhash().unwrap(),
    );
    match connection.send_and_confirm_transaction(&transaction) {
        Ok(signature) => println!("Transaction sent with signature: {}", signature),
        Err(err) => eprintln!("Error sending transaction: {:?}", err),
    }
}

合约销毁退存储费

同一个合约项目种重复deploy的话不会创建新的program_id

solana program close

全部评论(0)