Интеграция с IBC (Cosmos)
IBC (Inter-Blockchain Communication Protocol) — это то, что TCP/IP сделал для интернета, применённое к блокчейнам. Протокол позволяет суверенным блокчейнам Cosmos экосистемы безопасно передавать данные и токены без trusted intermediary. В отличие от большинства кросс-чейн решений, IBC не требует multisig-мостов или oracle комитетов — верификация происходит через light clients, криптографически встроенные в протокол. Это делает IBC фундаментально более безопасным, но и значительно более сложным в реализации.
Как IBC работает на уровне протокола
Основные компоненты
Light Client — каждый IBC-совместимый блокчейн хранит light client состояние контрчейна. Light client верифицирует consensus proof'ы (Merkle proof'ы) блоков другого chain'а без полной загрузки его истории. Поддерживаемые consensus: Tendermint/CometBFT, Solo Machine, ETH PoS (через 08-wasm light client для EVM).
Connection — двустороннее соединение между двумя light clients. Устанавливается через 4-way handshake (ConnOpenInit → ConnOpenTry → ConnOpenAck → ConnOpenConfirm).
Channel — логический канал поверх connection с определённой семантикой (ORDERED или UNORDERED). К каналу привязан конкретный IBC Application Protocol.
Packet — единица данных, передаваемая через channel. Содержит payload, timeout (высота блока или timestamp), sequence number.
Relayer — offchain процесс, который мониторит оба chain'а, забирает commitment proof'ы и relay'ит пакеты. Relayer не имеет привилегий — он только передаёт данные, верификация на стороне light client. Основные реализации: Hermes (Rust, от Informal Systems), Go Relayer (от Strangelabs), ts-relayer.
Жизненный цикл пакета
Chain A: Application.sendPacket() → IBC Core записывает commitment hash
↓
Relayer замечает commitment
Relayer запрашивает Merkle proof у Chain A
↓
Chain B: IBC Core верифицирует proof через light client Chain A
IBC Core вызывает Application.onRecvPacket()
↓
Chain A: Relayer relay'ит acknowledgement
IBC Core вызывает Application.onAcknowledgementPacket()
Если packet не доставлен до timeout: Chain B отклоняет пакет, Chain A вызывает onTimeoutPacket — средства возвращаются отправителю. Это built-in механизм атомарного возврата.
ICS-20: передача токенов
ICS-20 (Interchain Standards 20) — стандарт для fungible token transfer через IBC. Это наиболее распространённый use case.
Trace-based адресация токенов
Когда ATOM отправляется с Cosmos Hub на Osmosis через IBC, на Osmosis он существует как ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2. Этот хэш — denom trace: transfer/channel-0/uatom. Это означает: токен uatom, пришедший через channel-0 (channel к Cosmos Hub на стороне Osmosis).
Важно: при возврате токена обратно на Cosmos Hub, trace "разворачивается" — токен не создаётся заново, а сжигается escrow'ированная сумма на Osmosis и выдаётся оригинал на Hub.
CosmWasm: написание IBC-совместимого контракта
CosmWasm контракты могут нативно участвовать в IBC — открывать каналы, отправлять и получать пакеты:
use cosmwasm_std::{
entry_point, Binary, DepsMut, Env, IbcChannel, IbcChannelCloseMsg,
IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcPacketAckMsg,
IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, Response, StdResult,
};
// Handshake: проверяем, что подключается правильный counterparty
#[entry_point]
pub fn ibc_channel_open(
_deps: DepsMut,
_env: Env,
msg: IbcChannelOpenMsg,
) -> StdResult<IbcChannelOpenResponse> {
let channel = msg.channel();
// Проверяем ordering и версию
if channel.order != IbcOrder::Unordered {
return Err(StdError::generic_err("Only unordered channels supported"));
}
if channel.version != "my-protocol-v1" {
return Err(StdError::generic_err("Wrong protocol version"));
}
Ok(IbcChannelOpenResponse::None)
}
#[entry_point]
pub fn ibc_channel_connect(
deps: DepsMut,
_env: Env,
msg: IbcChannelConnectMsg,
) -> StdResult<Response> {
let channel = msg.channel();
// Сохраняем channel ID для дальнейших отправок
CHANNEL_ID.save(deps.storage, &channel.endpoint.channel_id)?;
Ok(Response::new())
}
// Получение пакета
#[entry_point]
pub fn ibc_packet_receive(
deps: DepsMut,
_env: Env,
msg: IbcPacketReceiveMsg,
) -> StdResult<IbcReceiveResponse> {
let packet_data: MyPacketData = from_binary(&msg.packet.data)?;
// Бизнес-логика обработки пакета
process_cross_chain_message(deps, packet_data)?;
// Возвращаем acknowledgement
let ack = Binary::from(br#"{"result":"ok"}"#);
Ok(IbcReceiveResponse::new().set_ack(ack))
}
// Подтверждение доставки
#[entry_point]
pub fn ibc_packet_ack(
deps: DepsMut,
_env: Env,
msg: IbcPacketAckMsg,
) -> StdResult<Response> {
// Обрабатываем acknowledgement — пакет доставлен
// Или ошибку если destination контракт вернул error ack
Ok(Response::new())
}
// Таймаут — пакет не доставлен
#[entry_point]
pub fn ibc_packet_timeout(
deps: DepsMut,
_env: Env,
msg: IbcPacketTimeoutMsg,
) -> StdResult<Response> {
// Возвращаем средства пользователю
refund_user(deps, &msg.packet)?;
Ok(Response::new())
}
Отправка IBC transfer из контракта
use cosmwasm_std::{coins, IbcMsg, IbcTimeout, IbcTimeoutBlock};
fn send_tokens_via_ibc(
env: &Env,
channel_id: String,
to_address: String,
amount: Coin,
) -> StdResult<Response> {
let timeout = IbcTimeout::with_both(
IbcTimeoutBlock {
revision: 1,
height: env.block.height + 1000, // ~1000 блоков от текущего
},
env.block.time.plus_seconds(3600), // или через час
);
let ibc_msg = IbcMsg::Transfer {
channel_id,
to_address,
amount,
timeout,
memo: Some("cross-chain transfer".to_string()),
};
Ok(Response::new().add_message(ibc_msg))
}
IBC для EVM: интеграция через Union и Polymer
Нативный IBC работает только на Cosmos SDK / CosmWasm чейнах. Для Ethereum и других EVM сетей существуют несколько подходов:
Polymer Protocol — Ethereum rollup, специально созданный для IBC messaging. Ethereum контракты взаимодействуют с Polymer Hub через специальный dispatcher контракт, который обеспечивает IBC sematics на EVM.
Union Protocol — ZK-based IBC client для EVM. Использует ZK proof'ы вместо委員会 для верификации Tendermint consensus, что позволяет иметь trustless IBC на Ethereum без multisig.
// Пример с Polymer IBC dispatcher
interface IbcDispatcher {
function sendPacket(
bytes32 channelId,
bytes calldata payload,
uint64 timeoutTimestamp
) external returns (uint64 sequence);
}
contract EVMIbcApp is IbcReceiverBase {
IbcDispatcher immutable dispatcher;
function sendCrossChainMessage(
bytes32 channelId,
bytes calldata data
) external {
uint64 timeoutTimestamp = uint64(block.timestamp + 3600) * 1e9; // nanoseconds
dispatcher.sendPacket(channelId, data, timeoutTimestamp);
}
function onRecvPacket(IbcPacket calldata packet)
external override
returns (AckPacket memory ack)
{
// Обработка входящего пакета от Cosmos chain
processIncomingData(packet.data);
return AckPacket(true, bytes("ok"));
}
}
Relayer инфраструктура
Без relayer'ов IBC не работает. Это критическая инфраструктура, которую нужно либо запускать самостоятельно, либо использовать сервисы.
Hermes relayer — конфигурация для связи двух chain'ов:
[global]
log_level = "info"
[[chains]]
id = "cosmoshub-4"
rpc_addr = "https://cosmos-rpc.example.com:26657"
grpc_addr = "https://cosmos-grpc.example.com:9090"
rpc_timeout = "15s"
account_prefix = "cosmos"
key_name = "relayer-key"
gas_multiplier = 1.2
max_gas = 4000000
default_gas = 100000
[[chains]]
id = "osmosis-1"
rpc_addr = "https://osmosis-rpc.example.com:26657"
grpc_addr = "https://osmosis-grpc.example.com:9090"
account_prefix = "osmo"
key_name = "relayer-key-osmo"
gas_multiplier = 1.1
max_gas = 25000000
Экономика relayer'а — relayer тратит gas на обоих chain'ах. В ICS-29 (Incentivized Relaying) протоколы могут встраивать fee в пакеты для компенсации relayer'ов. Для production системы либо запускаем свой relayer с достаточным funding, либо используем Relay Services (Notional, Imperator, StakeLab).
Типичные use cases
Cross-chain DEX — Osmosis использует IBC для получения токенов из других Cosmos chains. Swap ATOM → OSMO технически — это IBC transfer + swap в одном флоу.
Interchain Accounts (ICS-27) — управление аккаунтом на chain B с chain A. Смарт-контракт на Osmosis может напрямую вызывать staking операции на Cosmos Hub от имени пользователя.
Interchain Queries (ICQ) — чтение on-chain состояния другого блокчейна без выполнения транзакций. Используется для получения цен, балансов, governance результатов.
Сложность и сроки
| Задача | Срок |
|---|---|
| Базовая ICS-20 интеграция (transfer) | 1–2 нед |
| CosmWasm IBC контракт (кастомный протокол) | 3–6 нед |
| Relayer инфраструктура + мониторинг | 1–2 нед |
| EVM↔Cosmos через Polymer/Union | 4–8 нед |
| Interchain Accounts (ICS-27) | 3–5 нед |
IBC — не plug-and-play. Нужно глубокое понимание packet lifecycle, timeout механизмов и light client security. Ошибки в timeout handling = потеря средств. Для production интеграции рекомендуется аудит от команд с Cosmos-специализацией (Zellic, Oak Security).







