Перейти к основному содержимому

Среда выполнения контрактов

Среда выполнения контрактов Savitri исполняет смарт-контракты в изолированной среде с измерением газа, изоляцией хранилища и генерацией событий.

Поток выполнения

Contract Call TX arrives


BaseContract validation
│ check paused, owner, reserved slots

Gas Meter initialization
│ gas_limit from TX fee

ContractStorage setup
│ load contract state, init cache

Function dispatch
│ match function_selector → handler

Execution (with gas tracking)
│ SLOAD, SSTORE, events, calls

Result
├── Success → commit storage, emit events
└── Failure → revert all changes

BaseContract

Все контракты расширяют BaseContract. Слоты 0–99 зарезервированы:

СлотПолеРазмерОписание
0owner32 байтаАдрес владельца контракта
1versionu64Версия контракта
2governance_hookboolИнтеграция с управлением включена
3fee_hookboolПользовательская логика комиссий включена
4pausedboolСостояние паузы контракта
5–99Зарезервировано-Для будущего использования

Функции BaseContract

ФункцияДоступОписание
owner()ПубличныйПолучить владельца контракта
transfer_ownership(new_owner)Только владелецПередать право собственности
version()ПубличныйПолучить версию контракта
upgrade(new_version)Только владелецОбновить контракт
pause()Только владелецПриостановить все операции
unpause()Только владелецВозобновить операции

Измерение газа

Стоимость газа

ОперацияГазОписание
SLOAD100Чтение хранилища
SSTORE (новое)20 000Запись в хранилище (пустой слот)
SSTORE (обновление)5 000Запись в хранилище (существующий слот)
CALL2 300Межконтрактный вызов
CREATE32 000Развёртывание контракта
TRANSFER300Перевод токена
LOG375Генерация события (базовая)
LOG_TOPIC375За каждую дополнительную тему
LOG_DATA8За каждый байт данных события
CALLDATA16За каждый байт данных вызова

Пакетный учёт

Счётчик газа использует пакетный учёт (100 операций на пакет) для снижения накладных расходов. Газ фиксируется пакетами, а не за каждую операцию.

Лимит газа

Лимит газа вычисляется из комиссии транзакции:

gas_limit = tx.fee / gas_price

Если газ заканчивается во время выполнения, вся транзакция откатывается.

Хранилище контракта

Модель на основе слотов

Каждый контракт имеет независимое хранилище типа ключ-значение, где ключами являются номера слотов u64, а значениями — 32-байтовые массивы.

Вычисление слотов

Для маппингов слоты вычисляются с использованием Keccak256 для предотвращения коллизий:

// Simple value
slot = FIXED_SLOT_NUMBER

// Mapping (address → value)
slot = keccak256(address || base_slot)[0..8] as u64

// Nested mapping (address → address → value)
inner = keccak256(outer_key || base_slot)
slot = keccak256(inner_key || inner)[0..8] as u64

Дерево Меркла

Хранилище контракта поддерживает дерево Меркла для генерации доказательств состояния.

Система событий

Контракты генерируют события для внешних потребителей:

pub struct CustomEvent {
pub event_type: String, // e.g., "Transfer", "Approval"
pub topics: Vec<Vec<u8>>, // indexed fields
pub data: Vec<u8>, // non-indexed data
}

Стандартные события (из BaseContract):

  • OwnershipTransferred(old_owner, new_owner)
  • ContractUpgraded(old_version, new_version)
  • Paused(by)
  • Unpaused(by)

Развёртывание контрактов

1. Create DeployTransaction (to = None, data = bytecode)
2. Assign contract address (derived from deployer + nonce)
3. Initialize BaseContract (set owner, version)
4. Run contract constructor (initialize function)
5. Store ContractInfo in CF_CONTRACTS
6. Emit ContractDeployed event

Вызовы контрактов

1. Parse function_selector from TX data
2. Load contract from CF_CONTRACTS
3. Check BaseContract state (not paused, etc.)
4. Initialize GasMeter with gas_limit
5. Execute function with ContractStorage
6. If success: commit storage changes, deduct gas
7. If failure: revert all changes

Интерпретатор EVM

Модуль evm_interpreter обеспечивает базовое выполнение байткода EVM для совместимости с контрактами Ethereum. Это позволяет развёртывать контракты, скомпилированные на Solidity, в сети Savitri.

Мониторинг памяти

Модуль memory_monitor отслеживает использование памяти во время выполнения для предотвращения DoS-атак:

  • Лимиты памяти на контракт
  • Отслеживание выделений памяти
  • Автоматическое завершение при превышении лимитов

Параллельное выполнение

Модуль parallel обеспечивает параллельное выполнение контрактов для независимых транзакций:

  • Анализ зависимостей между транзакциями
  • Обнаружение конфликтов в слотах хранилища
  • Параллельное выполнение неконфликтующих транзакций
  • Последовательное выполнение в качестве запасного варианта для конфликтующих транзакций

Трассировка контрактов

Модуль tracing предоставляет трассировку выполнения для отладки:

  • Пошаговый журнал выполнения
  • Отслеживание чтения/записи хранилища
  • Потребление газа на каждую операцию
  • Журнал генерации событий