solana智能合约 rust语言 转账黑白名单代码

2024-08-22 19:12

本文主要是介绍solana智能合约 rust语言 转账黑白名单代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 Solana 中,智能合约(也称为链上程序或 Program)主要是使用 Rust 语言编写的。为了实现一个转账功能,并带有黑白名单限制,我们需要创建一个智能合约,该合约能够接收转账请求,并根据预设的黑白名单规则来决定是否允许转账。
下面是一个简单的 Rust 代码示例,展示了如何在 Solana 上实现这样的智能合约。这个示例假设已经熟悉了 Solana 的基本概念和 Rust 语言的基本语法。
步骤 1: 安装和设置环境
确保已经安装了 Solana CLI 和 Rust 工具链。可以通过 Solana 官方文档来获取这些工具。

   # 对于 macOS 和 Linuxsh <(curl -sSfL https://release.solana.com/v1.10.21/install)# 或者对于 Windowspowershell -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://release.solana.com/v1.10.21/install.ps1'))"


步骤 2: 创建一个新的 Solana 程序
使用 Solana CLI 创建一个新的 Rust 程序项目:

solana program init --template rust
cd my_program

步骤 3: 编写智能合约代码
打开 src/lib.rs 文件,并替换其中的内容为以下代码:

use solana_program::{account_info::AccountInfo,entrypoint::{program_error::PrintProgramError, ProgramResult},msg,program::invoke,program_error::ProgramError,pubkey::Pubkey,system_instruction,sysvar::Sysvar,
};// 定义转账指令的参数结构
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TransferArgs {pub amount: u64,
}// 定义账户元数据
#[derive(Accounts)]
pub struct TransferContext<'info> {#[account(mut)]pub from: AccountInfo<'info>,#[account(mut)]pub to: AccountInfo<'info>,pub system_program: AccountInfo<'info>,
}/// 转账指令处理器
pub fn process_transfer(program_id: &Pubkey,accounts: TransferContext,transfer_args: TransferArgs,
) -> ProgramResult {let TransferContext {from,to,system_program,} = accounts;// 检查转账金额是否大于0if transfer_args.amount == 0 {msg!("Amount must be greater than zero");return Err(ProgramError::InvalidArgument);}// 检查黑名单if is_blacklisted(from.key) {msg!("Account is blacklisted");return Err(ProgramError::InvalidAccountData);}// 检查白名单if !is_whitelisted(to.key) {msg!("Recipient is not whitelisted");return Err(ProgramError::InvalidAccountData);}// 执行转账invoke(&system_instruction::transfer(from.key, to.key, transfer_args.amount),&[from.clone(), to.clone(), system_program.clone()],)?;Ok(())
}/// 检查账户是否在黑名单中
fn is_blacklisted(account: &Pubkey) -> bool {// 这里应该有一个真正的黑名单列表let blacklist = vec![Pubkey::new_unique(),Pubkey::new_unique(),];blacklist.contains(account)
}/// 检查账户是否在白名单中
fn is_whitelisted(account: &Pubkey) -> bool {// 这里应该有一个真正的白名单列表let whitelist = vec![Pubkey::new_unique(),Pubkey::new_unique(),];whitelist.contains(account)
}// 入口点
solana_program::entrypoint!(process_instruction);// 处理指令
fn process_instruction(program_id: &Pubkey,accounts: &[AccountInfo],instruction_data: &[u8],
) -> ProgramResult {let accounts_iter = &mut accounts.iter();// 解析指令数据let transfer_args = TransferArgs::unpack_from_slice(instruction_data)?;// 解析账户元数据let accounts = TransferContext::try_from_iter(accounts_iter)?;// 处理转账指令process_transfer(program_id, accounts, transfer_args)
}

步骤 4: 编译和部署
使用 Solana CLI 编译并部署智能合约:

solana program build
solana program deploy target/deploy/my_program.so

步骤 5: 测试智能合约
可以使用 Solana 的 solana-keygen 或者 spl-token 工具来创建账户和测试转账功能。确保在测试之前向账户充值足够的 SOL 以便进行转账操作。
注意事项
在实际应用中,黑名单和白名单应该存储在一个更安全的地方,比如使用链上存储或其他方式。
本示例简化了许多细节,例如错误处理和账户验证。
确保在生产环境中对所有输入进行严格的验证和错误处理。
以上代码提供了一个基本的框架,可以在此基础上扩展更多的功能和安全性检查。

步骤 6: 扩展功能和安全性
接下来,我们可以进一步完善和扩展智能合约的功能,以增强其安全性和实用性。以下是一些建议:
增加账户权限管理:
可以为账户分配不同的角色,如管理员、普通用户等。
管理员账户可以修改黑名单和白名单。
动态更新黑白名单:
允许管理员账户动态地添加或删除黑名单和白名单中的账户。
增加日志记录:
记录每次转账的操作详情,包括转账金额、时间戳、发起者和接收者的账户信息等。
增加余额检查:
在转账前检查发起者账户是否有足够的余额。
增加交易限额:
限制单次转账的最大金额。
增加多重签名支持:
对于大额交易,可以要求多个账户共同确认。
示例代码扩展
1. 动态更新黑白名单
首先,我们需要在智能合约中增加一个管理员账户,以及相关的指令来更新黑白名单。

use solana_program::{account_info::AccountInfo,entrypoint::{program_error::PrintProgramError, ProgramResult},msg,program::invoke,program_error::ProgramError,pubkey::Pubkey,system_instruction,sysvar::Sysvar,
};// 定义转账指令的参数结构
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TransferArgs {pub amount: u64,
}// 定义更新黑白名单的参数结构
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct UpdateListArgs {pub account: Pubkey,pub is_blacklist: bool,
}// 定义账户元数据
#[derive(Accounts)]
pub struct TransferContext<'info> {#[account(mut)]pub from: AccountInfo<'info>,#[account(mut)]pub to: AccountInfo<'info>,pub system_program: AccountInfo<'info>,pub admin: AccountInfo<'info>, // 新增管理员账户
}impl<'info> TransferContext<'info> {pub fn try_from_iter(accounts_iter: &mut std::iter::Peekable<std::slice::Iter<'info, AccountInfo<'info>>>) -> ProgramResult {let from = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let to = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let system_program = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let admin = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;Ok(TransferContext {from: from.clone(),to: to.clone(),system_program: system_program.clone(),admin: admin.clone(),})}
}/// 转账指令处理器
pub fn process_transfer(program_id: &Pubkey,accounts: TransferContext,transfer_args: TransferArgs,
) -> ProgramResult {let TransferContext {from,to,system_program,admin,} = accounts;// 检查转账金额是否大于0if transfer_args.amount == 0 {msg!("Amount must be greater than zero");return Err(ProgramError::InvalidArgument);}// 检查黑名单if is_blacklisted(from.key, admin) {msg!("Account is blacklisted");return Err(ProgramError::InvalidAccountData);}// 检查白名单if !is_whitelisted(to.key, admin) {msg!("Recipient is not whitelisted");return Err(ProgramError::InvalidAccountData);}// 执行转账invoke(&system_instruction::transfer(from.key, to.key, transfer_args.amount),&[from.clone(), to.clone(), system_program.clone()],)?;Ok(())
}/// 更新黑白名单指令处理器
pub fn process_update_list(program_id: &Pubkey,accounts: TransferContext,update_args: UpdateListArgs,
) -> ProgramResult {let TransferContext {admin,..} = accounts;// 检查是否为管理员账户if !admin_is_admin(admin.key) {msg!("Not an admin account");return Err(ProgramError::InvalidAccountData);}// 更新黑白名单if update_args.is_blacklist {add_to_blacklist(update_args.account);} else {add_to_whitelist(update_args.account);}Ok(())
}/// 检查账户是否在黑名单中
fn is_blacklisted(account: &Pubkey, admin: &AccountInfo) -> bool {// 这里应该有一个真正的黑名单列表let blacklist = get_blacklist(admin);blacklist.contains(account)
}/// 检查账户是否在白名单中
fn is_whitelisted(account: &Pubkey, admin: &AccountInfo) -> bool {// 这里应该有一个真正的白名单列表let whitelist = get_whitelist(admin);whitelist.contains(account)
}/// 获取黑名单列表
fn get_blacklist(admin: &AccountInfo) -> Vec<Pubkey> {// 这里应该从管理员账户读取黑名单列表vec![Pubkey::new_unique(),Pubkey::new_unique(),]
}/// 获取白名单列表
fn get_whitelist(admin: &AccountInfo) -> Vec<Pubkey> {// 这里应该从管理员账户读取白名单列表vec![Pubkey::new_unique(),Pubkey::new_unique(),]
}/// 检查是否为管理员账户
fn admin_is_admin(account: &Pubkey) -> bool {// 这里应该有一个真正的管理员账户列表let admins = vec![Pubkey::new_unique(),Pubkey::new_unique(),];admins.contains(account)
}/// 添加账户到黑名单
fn add_to_blacklist(account: Pubkey) {// 这里应该更新黑名单列表
}/// 添加账户到白名单
fn add_to_whitelist(account: Pubkey) {// 这里应该更新白名单列表
}// 入口点
solana_program::entrypoint!(process_instruction);// 处理指令
fn process_instruction(program_id: &Pubkey,accounts: &[AccountInfo],instruction_data: &[u8],
) -> ProgramResult {let accounts_iter = &mut accounts.iter();match instruction_data[0] {0 => {let transfer_args = TransferArgs::unpack_from_slice(&instruction_data[1..])?;let accounts = TransferContext::try_from_iter(accounts_iter)?;process_transfer(program_id, accounts, transfer_args)},1 => {let update_args = UpdateListArgs::unpack_from_slice(&instruction_data[1..])?;let accounts = TransferContext::try_from_iter(accounts_iter)?;process_update_list(program_id, accounts, update_args)},_ => Err(ProgramError::InvalidInstructionData),}
}

步骤 7: 测试扩展功能
可以使用 Solana 的命令行工具来测试这些新的功能。确保在测试之前已经部署了最新的智能合约版本。
测试转账功能:
使用管理员账户添加一些账户到黑白名单。
测试正常转账和黑名单、白名单限制下的转账。
测试更新黑白名单功能:
使用管理员账户尝试添加和删除账户到黑白名单。
检查更新是否生效。
注意事项
在实际应用中,黑白名单应该存储在一个安全的地方,并且需要考虑数据的持久化问题。
确保在生产环境中对所有输入进行严格的验证和错误处理。
在处理敏感操作时,如更新黑白名单,应确保只有授权的管理员账户可以执行这些操作。
以上示例代码提供了一个基础框架,可以在此基础上进一步扩展和完善功能。

测试代码

为了测试上述智能合约的功能,我们可以编写一些简单的测试脚本来模拟转账和更新黑白名单的操作。这里我们将使用 Rust 语言和 Solana 提供的测试框架来进行测试。
步骤 1: 设置测试环境
确保你的项目中包含了测试依赖项。在 Cargo.toml 文件中添加以下内容:

[dependencies]
solana-program-test = "0.2"
solana-sdk = "1.14"[dev-dependencies]
solana-program-test = "0.2"
solana-sdk = "1.14"

步骤 2: 编写测试脚本
创建一个名为 tests.rs 的文件,并添加以下测试代码:

use solana_program_test::*;
use solana_sdk::{signature::{Keypair, Signer},transaction::Transaction,system_instruction,system_program,pubkey::Pubkey,
};
use my_program; // 替换为你的智能合约模块名称// 测试用的账户密钥对
let alice = Keypair::new();
let bob = Keypair::new();
let admin = Keypair::new();
let blacklisted_account = Keypair::new();
let whitelisted_account = Keypair::new();// 测试用的转账金额
const TRANSFER_AMOUNT: u64 = 100;#[tokio::test]
async fn test_transfer() {let mut test_context = TestContext::new().await;let program_id = test_context.add_program("my_program", my_program::id(), None).await;// 初始化账户initialize_accounts(&mut test_context, &program_id).await;// 测试正常转账test_normal_transfer(&mut test_context, &program_id).await.unwrap();// 测试黑名单转账test_blacklist_transfer(&mut test_context, &program_id).await.unwrap();// 测试白名单转账test_whitelist_transfer(&mut test_context, &program_id).await.unwrap();
}// 初始化账户
async fn initialize_accounts(test_context: &mut TestContext, program_id: &Pubkey) {// 给 Alice 和 Bob 账户各充 1000 SOLtest_context.bank_client.airdrop(&alice.pubkey(), 1000).await.unwrap();test_context.bank_client.airdrop(&bob.pubkey(), 1000).await.unwrap();// 将 Alice 设置为管理员set_admin(&mut test_context, &program_id, &alice.pubkey()).await.unwrap();// 将 blacklisted_account 添加到黑名单add_to_blacklist(&mut test_context, &program_id, &blacklisted_account.pubkey()).await.unwrap();// 将 whitelisted_account 添加到白名单add_to_whitelist(&mut test_context, &program_id, &whitelisted_account.pubkey()).await.unwrap();
}// 测试正常转账
async fn test_normal_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), TRANSFER_AMOUNT)],Some(&alice.pubkey()),&[&alice],test_context.last_blockhash,);test_context.bank_client.process_transaction(tx).await.map_err(|_| solana_program::program_error::ProgramError::InvalidAccountData)?;Ok(())
}// 测试黑名单转账
async fn test_blacklist_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[system_instruction::transfer(&blacklisted_account.pubkey(), &bob.pubkey(), TRANSFER_AMOUNT)],Some(&blacklisted_account.pubkey()),&[&blacklisted_account],test_context.last_blockhash,);assert!(test_context.bank_client.process_transaction(tx).await.is_err());Ok(())
}// 测试白名单转账
async fn test_whitelist_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[system_instruction::transfer(&alice.pubkey(), &whitelisted_account.pubkey(), TRANSFER_AMOUNT)],Some(&alice.pubkey()),&[&alice],test_context.last_blockhash,);test_context.bank_client.process_transaction(tx).await.map_err(|_| solana_program::program_error::ProgramError::InvalidAccountData)?;Ok(())
}// 设置管理员账户
async fn set_admin(test_context: &mut TestContext, program_id: &Pubkey, admin_key: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[my_program::instruction::set_admin(*program_id, *admin_key)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,);test_context.bank_client.process_transaction(tx).await.map_err(|_| solana_program::program_error::ProgramError::InvalidAccountData)?;Ok(())
}// 添加账户到黑名单
async fn add_to_blacklist(test_context: &mut TestContext, program_id: &Pubkey, account_key: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[my_program::instruction::add_to_blacklist(*program_id, *account_key)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,);test_context.bank_client.process_transaction(tx).await.map_err(|_| solana_program::program_error::ProgramError::InvalidAccountData)?;Ok(())
}// 添加账户到白名单
async fn add_to_whitelist(test_context: &mut TestContext, program_id: &Pubkey, account_key: &Pubkey) -> Result<(), solana_program::program_error::ProgramError> {let tx = Transaction::new_signed_with_payer(&[my_program::instruction::add_to_whitelist(*program_id, *account_key)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,);test_context.bank_client.process_transaction(tx).await.map_err(|_| solana_program::program_error::ProgramError::InvalidAccountData)?;Ok(())
}

步骤 3: 更新智能合约代码 (续)
接下来,我们将在智能合约中添加用于测试的指令,如设置管理员、添加到黑名单和白名单等。
1. 更新智能合约代码
首先,在智能合约中定义新的指令处理器,用于设置管理员、添加到黑名单和白名单等操作。

use solana_program::{account_info::AccountInfo,entrypoint::{program_error::PrintProgramError, ProgramResult},msg,program::invoke,program_error::ProgramError,pubkey::Pubkey,system_instruction,sysvar::Sysvar,
};// 定义转账指令的参数结构
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TransferArgs {pub amount: u64,
}// 定义更新黑白名单的参数结构
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct UpdateListArgs {pub account: Pubkey,pub is_blacklist: bool,
}// 定义账户元数据
#[derive(Accounts)]
pub struct TransferContext<'info> {#[account(mut)]pub from: AccountInfo<'info>,#[account(mut)]pub to: AccountInfo<'info>,pub system_program: AccountInfo<'info>,pub admin: AccountInfo<'info>, // 新增管理员账户
}impl<'info> TransferContext<'info> {pub fn try_from_iter(accounts_iter: &mut std::iter::Peekable<std::slice::Iter<'info, AccountInfo<'info>>>) -> ProgramResult {let from = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let to = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let system_program = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;let admin = accounts_iter.next().ok_or(ProgramError::MissingAccount)?;Ok(TransferContext {from: from.clone(),to: to.clone(),system_program: system_program.clone(),admin: admin.clone(),})}
}/// 转账指令处理器
pub fn process_transfer(program_id: &Pubkey,accounts: TransferContext,transfer_args: TransferArgs,
) -> ProgramResult {let TransferContext {from,to,system_program,admin,} = accounts;// 检查转账金额是否大于0if transfer_args.amount == 0 {msg!("Amount must be greater than zero");return Err(ProgramError::InvalidArgument);}// 检查黑名单if is_blacklisted(from.key, admin) {msg!("Account is blacklisted");return Err(ProgramError::InvalidAccountData);}// 检查白名单if !is_whitelisted(to.key, admin) {msg!("Recipient is not whitelisted");return Err(ProgramError::InvalidAccountData);}// 执行转账invoke(&system_instruction::transfer(from.key, to.key, transfer_args.amount),&[from.clone(), to.clone(), system_program.clone()],)?;Ok(())
}/// 设置管理员指令处理器
pub fn process_set_admin(program_id: &Pubkey,accounts: TransferContext,admin_key: Pubkey,
) -> ProgramResult {let TransferContext {admin,..} = accounts;// 检查是否为当前管理员账户if !admin_is_admin(admin.key) {msg!("Not an admin account");return Err(ProgramError::InvalidAccountData);}// 更新管理员账户update_admin(admin_key);Ok(())
}/// 添加到黑名单指令处理器
pub fn process_add_to_blacklist(program_id: &Pubkey,accounts: TransferContext,account_key: Pubkey,
) -> ProgramResult {let TransferContext {admin,..} = accounts;// 检查是否为管理员账户if !admin_is_admin(admin.key) {msg!("Not an admin account");return Err(ProgramError::InvalidAccountData);}// 添加账户到黑名单add_to_blacklist(account_key);Ok(())
}/// 添加到白名单指令处理器
pub fn process_add_to_whitelist(program_id: &Pubkey,accounts: TransferContext,account_key: Pubkey,
) -> ProgramResult {let TransferContext {admin,..} = accounts;// 检查是否为管理员账户if !admin_is_admin(admin.key) {msg!("Not an admin account");return Err(ProgramError::InvalidAccountData);}// 添加账户到白名单add_to_whitelist(account_key);Ok(())
}/// 检查账户是否在黑名单中
fn is_blacklisted(account: &Pubkey, admin: &AccountInfo) -> bool {// 这里应该有一个真正的黑名单列表let blacklist = get_blacklist(admin);blacklist.contains(account)
}/// 检查账户是否在白名单中
fn is_whitelisted(account: &Pubkey, admin: &AccountInfo) -> bool {// 这里应该有一个真正的白名单列表let whitelist = get_whitelist(admin);whitelist.contains(account)
}/// 获取黑名单列表
fn get_blacklist(admin: &AccountInfo) -> Vec<Pubkey> {// 这里应该从管理员账户读取黑名单列表vec![Pubkey::new_unique(),Pubkey::new_unique(),]
}/// 获取白名单列表
fn get_whitelist(admin: &AccountInfo) -> Vec<Pubkey> {// 这里应该从管理员账户读取白名单列表vec![Pubkey::new_unique(),Pubkey::new_unique(),]
}/// 检查是否为管理员账户
fn admin_is_admin(account: &Pubkey) -> bool {// 这里应该有一个真正的管理员账户列表let admins = vec![Pubkey::new_unique(),Pubkey::new_unique(),];admins.contains(account)
}/// 更新管理员账户
fn update_admin(new_admin: Pubkey) {// 这里应该更新管理员账户列表
}/// 添加账户到黑名单
fn add_to_blacklist(account: Pubkey) {// 这里应该更新黑名单列表
}/// 添加账户到白名单
fn add_to_whitelist(account: Pubkey) {// 这里应该更新白名单列表
}// 入口点
solana_program::entrypoint!(process_instruction);// 处理指令
fn process_instruction(program_id: &Pubkey,accounts: &[AccountInfo],instruction_data: &[u8],
) -> ProgramResult {let accounts_iter = &mut accounts.iter();match instruction_data[0] {0 => {let transfer_args = TransferArgs::unpack_from_slice(&instruction_data[1..])?;let accounts = TransferContext::try_from_iter(accounts_iter)?;process_transfer(program_id, accounts, transfer_args)},1 => {let admin_key = Pubkey::new_unique();let accounts = TransferContext::try_from_iter(accounts_iter)?;process_set_admin(program_id, accounts, admin_key)},2 => {let account_key = Pubkey::new_unique();let accounts = TransferContext::try_from_iter(accounts_iter)?;process_add_to_blacklist(program_id, accounts, account_key)},3 => {let account_key = Pubkey::new_unique();let accounts = TransferContext::try_from_iter(accounts_iter)?;process_add_to_whitelist(program_id, accounts, account_key)},_ => Err(ProgramError::InvalidInstructionData),}
}

步骤 4: 更新测试代码
现在我们需要更新测试代码以使用新的指令处理器。以下是更新后的测试代码:

use solana_program_test::*;
use solana_sdk::{signature::{Keypair, Signer},transaction::Transaction,system_instruction,system_program,pubkey::Pubkey,
};
use my_program; // 替换为你的智能合约模块名称// 测试用的账户密钥对
let alice = Keypair::new();
let bob = Keypair::new();
let admin = Keypair::new();
let blacklisted_account = Keypair::new();
let whitelisted_account = Keypair::new();// 测试用的转账金额
const TRANSFER_AMOUNT: u64 = 100;#[tokio::test]
async fn test_transfer() {let mut test_context = TestContext::new().await;let program_id = test_context.add_program("my_program", my_program::id(), None).await;// 初始化账户initialize_accounts(&mut test_context, &program_id).await;// 测试正常转账test_normal_transfer(&mut test_context, &program_id).await.unwrap();// 测试黑名单转账test_blacklist_transfer(&mut test_context, &program_id).await.unwrap();// 测试白名单转账test_whitelist_transfer(&mut test_context, &program_id).await.unwrap();
}// 初始化账户 
async fn initialize_accounts(test_context: &mut TestContext, program_id: &Pubkey) {// 创建并初始化账户test_context.banks_client.with_signer(&alice).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[system_instruction::create_account(&test_context.payer.pubkey(),&alice.pubkey(),1_000_000, // 初始资金1024, // 空间大小program_id,)],Some(&test_context.payer.pubkey()),&[&test_context.payer, &alice],test_context.last_blockhash,)).await.unwrap();test_context.banks_client.with_signer(&bob).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[system_instruction::create_account(&test_context.payer.pubkey(),&bob.pubkey(),1_000_000, // 初始资金1024, // 空间大小program_id,)],Some(&test_context.payer.pubkey()),&[&test_context.payer, &bob],test_context.last_blockhash,)).await.unwrap();test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[system_instruction::create_account(&test_context.payer.pubkey(),&admin.pubkey(),1_000_000, // 初始资金1024, // 空间大小program_id,)],Some(&test_context.payer.pubkey()),&[&test_context.payer, &admin],test_context.last_blockhash,)).await.unwrap();test_context.banks_client.with_signer(&blacklisted_account).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[system_instruction::create_account(&test_context.payer.pubkey(),&blacklisted_account.pubkey(),1_000_000, // 初始资金1024, // 空间大小program_id,)],Some(&test_context.payer.pubkey()),&[&test_context.payer, &blacklisted_account],test_context.last_blockhash,)).await.unwrap();test_context.banks_client.with_signer(&whitelisted_account).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[system_instruction::create_account(&test_context.payer.pubkey(),&whitelisted_account.pubkey(),1_000_000, // 初始资金1024, // 空间大小program_id,)],Some(&test_context.payer.pubkey()),&[&test_context.payer, &whitelisted_account],test_context.last_blockhash,)).await.unwrap();
}// 测试正常转账
async fn test_normal_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), ProgramError> {let transfer_args = TransferArgs { amount: TRANSFER_AMOUNT };let accounts = TransferContext::try_from_iter(&[&alice.pubkey(),&bob.pubkey(),&system_program::id(),&admin.pubkey(),]).unwrap();test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[solana_program::instruction::Instruction::new_with_borsh(*program_id,0, // 指令类型vec![accounts.from.clone(), accounts.to.clone(), accounts.system_program.clone(), accounts.admin.clone()],transfer_args,)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,)).await?;Ok(())
}// 测试黑名单转账
async fn test_blacklist_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), ProgramError> {// 将账户添加到黑名单let accounts = TransferContext::try_from_iter(&[&admin.pubkey(),&blacklisted_account.pubkey(),&system_program::id(),&admin.pubkey(),]).unwrap();test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[solana_program::instruction::Instruction::new_with_borsh(*program_id,2, // 指令类型vec![accounts.from.clone(), accounts.to.clone(), accounts.system_program.clone(), accounts.admin.clone()],UpdateListArgs { account: blacklisted_account.pubkey(), is_blacklist: true },)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,)).await?;// 尝试从黑名单账户转账let transfer_args = TransferArgs { amount: TRANSFER_AMOUNT };let accounts = TransferContext::try_from_iter(&[&blacklisted_account.pubkey(),&bob.pubkey(),&system_program::id(),&admin.pubkey(),]).unwrap();assert!(test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[solana_program::instruction::Instruction::new_with_borsh(*program_id,0, // 指令类型vec![accounts.from.clone(), accounts.to.clone(), accounts.system_program.clone(), accounts.admin.clone()],transfer_args,)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,)).await.is_err());Ok(())
}// 测试白名单转账
async fn test_whitelist_transfer(test_context: &mut TestContext, program_id: &Pubkey) -> Result<(), ProgramError> {// 将账户添加到白名单let accounts = TransferContext::try_from_iter(&[&admin.pubkey(),&whitelisted_account.pubkey(),&system_program::id(),&admin.pubkey(),]).unwrap();test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[solana_program::instruction::Instruction::new_with_borsh(*program_id,3, // 指令类型vec![accounts.from.clone(), accounts.to.clone(), accounts.system_program.clone(), accounts.admin.clone()],UpdateListArgs { account: whitelisted_account.pubkey(), is_blacklist: false },)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,)).await?;// 尝试向白名单账户转账let transfer_args = TransferArgs { amount: TRANSFER_AMOUNT };let accounts = TransferContext::try_from_iter(&[&alice.pubkey(),&whitelisted_account.pubkey(),&system_program::id(),&admin.pubkey(),]).unwrap();test_context.banks_client.with_signer(&admin).send_and_confirm_transaction(Transaction::new_signed_with_payer(&[solana_program::instruction::Instruction::new_with_borsh(*program_id,0, // 指令类型vec![accounts.from.clone(), accounts.to.clone(), accounts.system_program.clone(), accounts.admin.clone()],transfer_args,)],Some(&admin.pubkey()),&[&admin],test_context.last_blockhash,)).await?;Ok(())
}

总结
以上步骤完成了智能合约的更新,包括添加了新的指令处理器以支持设置管理员、添加到黑名单和白名单等功能,并更新了测试代码来验证这些功能。请注意,上述代码示例中的 get_blacklist, get_whitelist, admin_is_admin, update_admin, add_to_blacklist 和 add_to_whitelist 函数都需要根据实际情况实现,例如通过维护一个账户状态来存储这些列表。

这篇关于solana智能合约 rust语言 转账黑白名单代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097146

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型