Разработка параметрического страхования на блокчейне
Традиционное страхование — это субъективная оценка убытков, долгое урегулирование претензий, бумажный документооборот и риск отказа в выплате. Параметрическое страхование работает по-другому: выплата происходит автоматически при достижении заранее оговорённого параметра (температура ниже -20°C, цена ETH падает на 30%, задержка рейса более 3 часов). Блокчейн + oracle делают такое страхование полностью прозрачным и лишённым human error при расчёте выплат.
Как это работает на уровне протокола
Структура параметрического страхового контракта:
Страхователь → Policy (контракт) → Oracle (условие) → AutoPayout
↑
Risk Pool (ликвидность для выплат)
Ключевые компоненты:
Policy — индивидуальный страховой договор. Содержит параметры: застрахованный адрес, условие выплаты, сумму покрытия, период действия, уплаченную премию.
Risk Pool — пул ликвидности, из которого происходят выплаты. Аналог страхового резерва. Наполняется премиями страхователей и/или капиталом LP (liquidity providers).
Oracle — источник данных для проверки условия. Chainlink для ценовых данных, Chainlink Functions для кастомных API (погода, авиарейсы), UMA для субъективных параметров.
Trigger — функция проверки условия и инициации выплаты. Вызывается автоматически (Chainlink Automation) или вручную после наступления события.
Архитектура смарт-контрактов
Разбиваем на три контракта для разделения ответственности:
// 1. PolicyManager — управление полисами
contract PolicyManager {
struct Policy {
address holder;
address token; // валюта выплаты (USDC)
uint256 coverage; // сумма покрытия
uint256 premium; // уплаченная премия
uint256 startTime;
uint256 endTime;
bytes32 conditionId; // ссылка на условие в ConditionRegistry
PolicyStatus status;
}
enum PolicyStatus { Active, Triggered, Expired, Claimed }
mapping(bytes32 => Policy) public policies;
IConditionRegistry public conditionRegistry;
IRiskPool public riskPool;
function createPolicy(
address token,
uint256 coverage,
bytes32 conditionId,
uint256 duration
) external payable returns (bytes32 policyId) {
uint256 premium = calculatePremium(coverage, conditionId, duration);
require(msg.value >= premium || IERC20(token).transferFrom(msg.sender, address(this), premium));
policyId = keccak256(abi.encodePacked(msg.sender, conditionId, block.timestamp));
policies[policyId] = Policy({
holder: msg.sender,
token: token,
coverage: coverage,
premium: premium,
startTime: block.timestamp,
endTime: block.timestamp + duration,
conditionId: conditionId,
status: PolicyStatus.Active
});
riskPool.lockLiquidity(policyId, coverage);
emit PolicyCreated(policyId, msg.sender, coverage);
}
}
// 2. ConditionRegistry — реестр условий выплат
contract ConditionRegistry {
struct Condition {
ConditionType condType;
address oracle;
bytes32 feedId; // Chainlink feed ID
int256 threshold; // пороговое значение
ComparisonType comparison; // BELOW, ABOVE, EQUALS
uint256 confirmations; // количество подтверждений oracle
}
enum ConditionType { PriceFeed, CustomAPI, ManualOracle }
enum ComparisonType { Below, Above, Equals }
function checkCondition(bytes32 conditionId) public view returns (bool triggered, int256 currentValue) {
Condition storage cond = conditions[conditionId];
if (cond.condType == ConditionType.PriceFeed) {
(, int256 price,, uint256 updatedAt,) = AggregatorV3Interface(cond.oracle).latestRoundData();
// Проверка freshness данных
require(block.timestamp - updatedAt < STALE_THRESHOLD, "Stale oracle data");
currentValue = price;
triggered = _compare(price, cond.threshold, cond.comparison);
}
}
}
// 3. RiskPool — управление ликвидностью
contract RiskPool {
mapping(bytes32 => uint256) public lockedLiquidity;
uint256 public totalLocked;
uint256 public totalAvailable;
// LP могут вносить ликвидность и получать yield от премий
mapping(address => uint256) public lpShares;
uint256 public totalShares;
function deposit(uint256 amount) external {
USDC.transferFrom(msg.sender, address(this), amount);
uint256 shares = totalShares == 0 ? amount : (amount * totalShares) / totalAvailable;
lpShares[msg.sender] += shares;
totalShares += shares;
totalAvailable += amount;
}
function payout(bytes32 policyId, address recipient, uint256 amount) external onlyPolicyManager {
require(lockedLiquidity[policyId] >= amount, "Insufficient locked liquidity");
lockedLiquidity[policyId] -= amount;
totalLocked -= amount;
USDC.transfer(recipient, amount);
}
}
Oracle интеграция: главная техническая сложность
Весь протокол зависит от надёжности данных oracle. Три векторa атак, которые нужно закрыть:
Oracle manipulation через flash loan. Если условие выплаты — «цена ETH упала ниже $1000», злоумышленник берёт flash loan, продаёт ETH на DEX до нужной цены, получает выплату, выкупает ETH, возвращает loan. Защита: не использовать spot price от DEX оракулов. Только Chainlink Data Feeds с агрегацией от нескольких нод, или TWAP за период, несовместимый с flash loan (TWAP > 1 блока уже защищён).
Stale data. Chainlink oracle перестаёт обновляться (нод проблемы, сеть перегружена). latestRoundData() возвращает старые данные. Контракт должен проверять updatedAt и отклонять данные старше X минут.
(, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt <= MAX_STALENESS, "Oracle data too old");
require(price > 0, "Invalid price");
Single point of failure oracle. Один Chainlink feed — это доверие одному источнику. Для критических условий используем несколько oracle источников с медианой:
function getMedianPrice(address[] memory feeds) internal view returns (int256) {
int256[] memory prices = new int256[](feeds.length);
for (uint i = 0; i < feeds.length; i++) {
(, prices[i],,,) = AggregatorV3Interface(feeds[i]).latestRoundData();
}
return median(prices); // сортировка + средний элемент
}
Расчёт премий
Актуарная математика для смарт-контрактов — нетривиальная задача. Упрощённые подходы:
Фиксированный коэффициент. premium = coverage * rate, где rate задаётся администратором на основе исторических данных. Просто, но не адаптивно.
Динамическая премия через implied volatility. Для ценовых триггеров — премия растёт при высокой волатильности актива. Дороговато по gas для onchain расчёта. Решение: расчёт офчейн, подпись через EIP-712, верификация onchain.
Bonding curve для Risk Pool. Чем меньше свободной ликвидности в пуле — тем дороже новый полис. Это естественный механизм балансировки: при высоком спросе на покрытие цена растёт, привлекая новых LP.
Типы параметрических продуктов
| Продукт | Параметр | Oracle |
|---|---|---|
| Крипто price protection | Цена актива < N | Chainlink Price Feed |
| DeFi депозит страховка | TVL протокола < X | Кастомный + Chainlink |
| Авиастрахование | Задержка рейса > 3ч | Chainlink Functions + FlightAware API |
| Погодное страхование | Температура < -20°C | Chainlink + OpenWeatherMap |
| Смарт-контракт аудит | Exploit (TVL потеря > Y%) | Multisig oracle |
Regulatory considerations
DeFi страхование — регуляторно чувствительная область. Nexus Mutual работает как discretionary mutual, не страховщик. Etherisc получил лицензию в некоторых юрисдикциях. На уровне смарт-контрактов: terms of service, geoblocking для регулируемых рынков, KYC для выплат выше порога.
Процесс разработки
Проектирование (3-5 дней). Определяем продуктовую логику: типы полисов, oracle стратегию, Risk Pool механику, токеномику LP-токенов. Актуарный расчёт базовых ставок.
Разработка контрактов (7-10 дней). PolicyManager, ConditionRegistry, RiskPool. Интеграция Chainlink Automation для автоматических триггеров. Тесты на Foundry с форком mainnet — симулируем разные ценовые сценарии.
Security review (3-5 дней). Slither + Mythril. Особое внимание на oracle пути, arithmetic в расчёте премий (overflow/precision), reentrancy при payout.
Frontend и The Graph (5-7 дней). Subgraph для истории полисов, React-дашборд страхователя, LP-интерфейс.
Testnet и аудит (1-2 недели). Запуск на Sepolia/Mumbai, симуляция страховых событий, внешний аудит перед mainnet.
Общий срок для базового протокола с одним типом страхования — 4-6 недель. Полноценная мультипродуктовая платформа — 3-4 месяца.







