Фреймворк Anchor на Solana: что такое и как работает


Безопасность и валидация данных
Один из механизмов безопасности — макросы, которые позволяют описывать требования к аккаунтам — участникам транзакций, и автоматически проверяют их состояние.
Фрейм позволяет ограничить доступ к функциям смарт-контракта с помощью атрибутов для аккаунтов. Так, использование типа Signer гарантирует, что транзакция может быть выполнена только после цифровой подписи пользователя. Это важно для защиты операций с изменением данных, поскольку только владельцы соответствующих учетных записей могут выполнять действия.
Для более сложных проверок разработчики могут использовать макрос require!, который разрешает вручную задавать условия для выполнения транзакций. Если условие не выполнено, ошибка возвращается автоматически и отклоняет транзакцию. Это помогает избежать некорректных операций и защищает данные пользователей.
Rust, на котором основан Anchor, изначально защищен от таких распространенных ошибок, вроде переполнения целых чисел и проблемы с доступом к памяти.
Написание
Дальше мы поделимся инструкцией по разработке вашей программы, но до этого установите зависимости и настройте окружение. Фрейм работает поверх Rust и Solana CLI, поэтому сначала требуется скачать:
- Rust (через rustup)
- Solana CLI (через официальный установщик)
- Anchor (через Cargo)
При работе с проектом Anchor можно создать fork репозитория на GitHub для внесения изменений.
Программа состоит из трех частей. #[program] — основная логика, где описаны обработчики функций. #[derive(Accounts)] — предоставляет info об участвующих аккаунтах. #[account] — структуры для хранения данных в блокчейне.
Пример структуры:
#[program]
pub mod example {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}
#[account]
pub struct ExampleData {
pub value: u64,
}
Создадим новый проект с помощью команды:
anchor init my_anchor_project
use anchor_lang::prelude::*;
#[program]
pub mod my_anchor_project {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
msg!("Программа Anchor успешно инициализирована!");
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}
В этом коде:
- #[program] указывает, что это основная логика программы.
- Context<Initialize>
используется для управления учетными записями. msg! — сообщение (message) об успешном обновлении выводится через макрос msg!.
Создание записи в журнале
#[account]
pub struct JournalEntry {
pub author: Pubkey,
pub content: String,
}
pub fn create_entry(ctx: Context<CreateEntry>, content: String) -> Result<()> {
let entry = &mut ctx.accounts.entry;
entry.author = *ctx.accounts.author.key;
entry.content = content;
msg!("Создана новая запись в журнале: {}", entry.content);
Ok(())
}
#[derive(Accounts)]
pub struct CreateEntry<'info> {
#[account(init, payer = author, space = 8 + 32 + 256)]
pub entry: Account<'info, JournalEntry>,
#[account(mut)]
pub author: Signer<'info>,
pub system_program: Program<'info, System>,
}
Здесь:
- Аннотация #[account(init)] создает новый аккаунт (newaccount).
- payer = author означает, что пользователь оплачивает транзакцию.
- space = 8 + 32 + 256 выделяет память для записи.
Обновление записи журнала
pub fn update_entry(ctx: Context<UpdateEntry>, new_content: String) -> Result<()> {
let entry = &mut ctx.accounts.entry;
require!(entry.author == *ctx.accounts.author.key, CustomError::Unauthorized);
entry.content = new_content;
msg!("Запись обновлена: {}", entry.content);
Ok(())
}
#[derive(Accounts)]
pub struct UpdateEntry<'info> {
#[account(mut, has_one = author)]
pub entry: Account<'info, JournalEntry>,
pub author: Signer<'info>,
}
Удаление записи журнала
pub fn delete_entry(ctx: Context<DeleteEntry>) -> Result<()> {
require!(ctx.accounts.entry.author == *ctx.accounts.author.key, CustomError::Unauthorized);
Ok(())
}
#[derive(Accounts)]
pub struct DeleteEntry<'info> {
#[account(mut, close = author, has_one = author)]
pub entry: Account<'info, JournalEntry>,
#[account(mut)]
pub author: Signer<'info>,
}
Создание и развертывание программы
anchor build
anchor deploy
Подключение программы к пользовательскому интерфейсу
Устанавливаем зависимости:
npm install @project-serum/anchor @solana/web3.js
import * as anchor from "@project-serum/anchor";
const provider = anchor.AnchorProvider.local();
anchor.setProvider(provider);
const program = anchor.workspace.MyAnchorProject;
async function createEntry(content) {
const entryAccount = anchor.web3.Keypair.generate();
await program.rpc.createEntry(content, {
accounts: {
entry: entryAccount.publicKey,
author: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: [entryAccount],
});
console.log("Запись создана:", entryAccount.publicKey.toString());
}
Разработка на стороне клиента
Пример подключения программы:
import * as anchor from "@project-serum/anchor";
const provider = anchor.AnchorProvider.local(); // Локальный провайдер для тестов
anchor.setProvider(provider);
const program = anchor.workspace.MyAnchorProject; // Доступ к программе
Разработка on-chain программ
Onchain программы на «Солана» реализуются на языке Rust с использованием фреймворка Anchor. Они выполняются непосредственно на блокчейне, и это накладывает ограничения.
У каждой программы фиксированный объем памяти, поэтому данные оптимизируются. Результат выполнения программы всегда должен быть предсказуемым. Использование аккаунтов и операций требует оплаты в SOL. Anchor предоставляет макросы для более простого управления аккаунтами и транзакциями. Например, макрос #[account] определяет структуру данных, которая хранится в блокчейне.
Для разработки программ полезно использовать:
- Solana CLI, чтобы управлять сетью, аккаунтами и программами.
- Anchor CLI, чтобы упростить создание, тестирование и развертывание программ.
- Localnet, чтобы использовать локальную сеть для тестирования программ без затрат на SOL.
- Solana Explorer, чтобы получить интерфейс для просмотра транзакций, программ и аккаунтов.
- Solana Devnet, чтобы бесплатно развернуть программы для тестирования.
Можно использовать IDE с поддержкой Rust, например, Visual Studio Code с плагинами для Rust.
Разработка приложений на блокчейне Solana
Создаём масштабируемые децентрализованные приложения и смарт-контракты на базе Solana — одного из самых быстрых блокчейнов для высокопроизводительных DeFi и NFT проектов
Создание на примере
Создайте проект:
anchor init example_project
cd example_project
В lib.rs добавьте логику для записи данных:
use anchor_lang::prelude::*;
#[program]
pub mod example_project {
use super::*;
pub fn set_data(ctx: Context<SetData>, data: String) -> Result<()> {
let account = &mut ctx.accounts.data_account;
account.data = data;
msg!("Данные установлены!");
Ok(())
}
}
#[derive(Accounts)]
pub struct SetData<'info> {
#[account(init, payer = user, space = 8 + 64)]
pub data_account: Account<'info, DataAccount>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct DataAccount {
pub data: String,
}
anchor build
anchor deploy
А это — пример программы-счетчика:
use anchor_lang::prelude::*;
#[program]
pub mod counter_program {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
counter.count = 0;
msg!("Счетчик инициализирован!");
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
counter.count += 1;
msg!("Счетчик увеличен до {}", counter.count);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = user, space = 8 + 8)]
pub counter: Account<'info, Counter>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut)]
pub counter: Account<'info, Counter>,
}
#[account]
pub struct Counter {
pub count: u64,
}
Что еще важно знать
При работе с памятью стоит учитывать строгое ограничение на размер данных. В отличие от традиционных баз данных, хранение информации в блокчейне платное и требует эффективного использования ресурсов. Anchor позволяет частично решить эту проблему за счет использования структур данных с минимальным накладным расходом и макросов для экономного управления памятью.
Кроме того, Anchor предоставляет безопасную модель разработки, автоматически генерируя проверки прав доступа и условия выполнения транзакций. Но разработчику все равно нужно следить за безопасностью своих программ. Например, важно корректно настраивать проверку прав на запись и выполнение, чтобы предотвратить несанкционированные изменения данных.
Еще одна деталь — интеграция с клиентской стороной через JavaScript и TypeScript. Библиотека @project-serum/anchor облегчает взаимодействие с программами через удобные функции по вызову методов контрактов. Тем не менее, необходимо понимать RPC-запросы и работу с ключами доступа.
Тестирование тоже важно. Anchor дает встроенные инструменты для локального тестирования программ — нет необходимости развертывать их в публичной сети. Это позволяет разработчикам быстрее находить ошибки и оптимизировать код.
Фреймворк заметно упрощает работу со смарт-контрактами на Solana. Код можно написать быстрее, безопаснее и с меньшим количеством ошибок. За счет удобного API и встроенных инструментов для работы с учетными записями, он снижает порог входа для новых разработчиков. Создавать децентрализованные приложения становится проще, а код программы можно выложить на GitHub для общего доступа и контроля версий.
Больше интересных статей

Энциклопедия
Как работают смарт-контракты на Solana: полный разбор и советы по использованию
Редакция MetaLamp




Как работают смарт-контракты на Solana: полный разбор и советы по использованию
Редакция MetaLamp
Энциклопедия


Лучшие перспективные GameFi проекты — 2025: возможность заработать в мире блокчейн-игр
Редакция MetaLamp
Энциклопедия





Что такое yield farming и как разработать платформу для него
Редакция MetaLamp

Протоколы ликвидности в DeFi: как они работают и зачем нужны
Редакция MetaLamp
