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

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

智能交通(二)——Spinger特刊推荐

特刊征稿 01  期刊名称: Autonomous Intelligent Systems  特刊名称: Understanding the Policy Shift  with the Digital Twins in Smart  Transportation and Mobility 截止时间: 开放提交:2024年1月20日 提交截止日

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d