# escrow Двусторонний trustless escrow. Buyer блокирует средства в contract treasury. Seller выполняет условие. Buyer подтверждает или открывает спор. При споре admin-арбитр решает исход. ## Жизненный цикл ``` buyer seller admin │ │ │ │─ create ─────▶│ │ treasury ← amount (locked) │ (seller, │ │ status: active │ amount) │ │ │ │ │ │ [seller delivered] │ │ │ │ │─ release ────▶│ │ treasury → seller │ │ │ status: released OR: │─ dispute ────▶│ │ status: disputed │ │─ dispute ────▶│ (either party can) │ │ │ │ │ │─ resolve(winner=buyer) ──▶ │ │ │ treasury → buyer │ │ │ status: refunded │ │ │ │ │ │─ resolve(winner=seller) ──▶ │ │ │ treasury → seller │ │ │ status: released OR: │ │─ refund ─────▶│ treasury → buyer (voluntary) │ │ │ status: refunded ``` **Статусы:** `active` → `released` / `refunded` / `disputed` ## Методы ### `init` Установить caller как admin (арбитр споров). **Аргументы:** нет Вызывается один раз после деплоя (deploy-скрипт делает автоматически). ```bash client call-contract --method init \ --contract $ESC_ID --key /keys/node1.json \ --gas 5000 --node http://node1:8080 ``` --- ### `create` Buyer создаёт escrow и блокирует средства. **Аргументы:** | # | Имя | Тип | Описание | |---|-----|-----|---------| | 0 | `id` | string | Уникальный ID эскроу (задаёт пользователь) | | 1 | `seller` | string | Pubkey продавца (hex) | | 2 | `amount` | uint64 | Сумма в µT | **Поведение:** - Переводит `amount` с caller (buyer) → treasury - Сохраняет buyer, seller, amount, status=active - Лог: `created: ` **Ограничения:** - ID должен быть уникальным — если `cstate[e::b]` уже есть, tx отклоняется ```bash client call-contract --method create \ --arg "deal-001" \ --arg \ --arg64 10000000 \ --contract $ESC_ID --key /tmp/buyer.json \ --gas 30000 --node http://node1:8080 ``` --- ### `release` Buyer подтверждает получение и освобождает средства seller'у. **Аргументы:** | # | Имя | Тип | |---|-----|-----| | 0 | `id` | string | **Права:** только buyer. **Статус:** должен быть `active`. **Поведение:** - Переводит `amount` с treasury → seller - Статус → released - Лог: `released: ` ```bash client call-contract --method release --arg "deal-001" \ --contract $ESC_ID --key /tmp/buyer.json \ --gas 20000 --node http://node1:8080 ``` --- ### `refund` Seller добровольно возвращает деньги buyer'у. **Аргументы:** | # | Имя | Тип | |---|-----|-----| | 0 | `id` | string | **Права:** только seller. **Статус:** должен быть `active`. **Поведение:** - Переводит `amount` с treasury → buyer - Статус → refunded - Лог: `refunded: ` ```bash client call-contract --method refund --arg "deal-001" \ --contract $ESC_ID --key /tmp/seller.json \ --gas 20000 --node http://node1:8080 ``` --- ### `dispute` Открыть спор. Может вызвать buyer или seller. **Аргументы:** | # | Имя | Тип | |---|-----|-----| | 0 | `id` | string | **Статус:** должен быть `active`. **Поведение:** - Статус → disputed - Лог: `disputed: ` - Средства остаются заблокированы в treasury ```bash client call-contract --method dispute --arg "deal-001" \ --contract $ESC_ID --key /tmp/buyer.json \ --gas 10000 --node http://node1:8080 ``` --- ### `resolve` Admin разрешает спор. **Аргументы:** | # | Имя | Тип | Значения | |---|-----|-----|---------| | 0 | `id` | string | ID эскроу | | 1 | `winner` | string | `buyer` или `seller` | **Права:** только admin. **Статус:** должен быть `disputed`. **Поведение:** - `winner=buyer` → treasury → buyer, статус → refunded - `winner=seller` → treasury → seller, статус → released - Лог: `resolved: ` ```bash # Admin решает в пользу buyer client call-contract --method resolve \ --arg "deal-001" --arg buyer \ --contract $ESC_ID --key /keys/node1.json \ --gas 20000 --node http://node1:8080 # Admin решает в пользу seller client call-contract --method resolve \ --arg "deal-001" --arg seller \ --contract $ESC_ID --key /keys/node1.json \ --gas 20000 --node http://node1:8080 ``` --- ### `info` Запросить состояние эскроу. **Аргументы:** | # | Имя | Тип | |---|-----|-----| | 0 | `id` | string | **Логи:** ``` buyer: seller: amount: <µT> status: active|released|refunded|disputed ``` ```bash client call-contract --method info --arg "deal-001" \ --contract $ESC_ID --key /keys/node1.json \ --gas 5000 --node http://node1:8080 ``` --- ## State Layout ``` cstate::admin → admin pubkey cstate::e::b → buyer pubkey cstate::e::s → seller pubkey cstate::e::a → amount (uint64 big-endian) cstate::e::x → status byte ('a'=active, 'd'=disputed, 'r'=released, 'f'=refunded) ``` ## Полный сценарий с dispute ```bash # Параметры BUYER_KEY=/tmp/buyer.json SELLER_KEY=/tmp/seller.json ADMIN_KEY=/keys/node1.json ID="escrow-001" # 1. Buyer создаёт эскроу на 5 T docker exec node1 client call-contract \ --key $BUYER_KEY --contract $ESC_ID \ --method create \ --arg $ID --arg $SELLER_PUB --arg64 5000000 \ --gas 30000 --node http://node1:8080 # 2. Проверить статус docker exec node1 client call-contract \ --key $BUYER_KEY --contract $ESC_ID \ --method info --arg $ID \ --gas 5000 --node http://node1:8080 # status: active # 3. Buyer не доволен — открывает спор docker exec node1 client call-contract \ --key $BUYER_KEY --contract $ESC_ID \ --method dispute --arg $ID \ --gas 10000 --node http://node1:8080 # 4. Admin рассматривает дело и решает в пользу seller docker exec node1 client call-contract \ --key $ADMIN_KEY --contract $ESC_ID \ --method resolve --arg $ID --arg seller \ --gas 20000 --node http://node1:8080 # Лог: resolved: escrow-001 # Seller получает 5 T ```