Додайте зрозуміле підписання до вашого протоколу за допомогою ERC-7730
Більшість великих експлойтів в Етеріумі мали однаковий останній крок: користувач схвалював транзакцію, яку не міг повноцінно зрозуміти. Апаратні гаманці показують необроблені шістнадцяткові дані виклику (calldata), і, що ще гірше, змушують вас вмикати сліпе підписання. Програмні гаманці показують розкодовані поля, але тільки тоді, коли вони розпізнають контракт. Коли ж вони цього не роблять — чи то через те, що протокол новий, застосунок скомпрометований, чи пристрій перебуває в автономному режимі — користувачі підписують наосліп.
ERC-7730 (opens in a new tab) визначає стандартний формат JSON для опису того, що означають виклики функцій вашого контракту.
Гаманець, який підтримує ERC-7730, зчитує ваш дескриптор і показує:
Обмін
Надіслати: 1,000 USDC
Отримати мінімум: 0.42 WETH
Протокол: Юнісвоп V3
Або єдине побудоване речення, зрозуміле як людям, так і агентам:
Обміняти 1,000 USDC на щонайменше 0.42 WETH
Замість селектора функції та списку необроблених цілих значень.
Це зрозуміле підписання (opens in a new tab) — «Що бачиш, те й підписуєш» (What You See Is What You Sign). Цей посібник допоможе вам написати дескриптор для власного контракту, перевірити його за допомогою офіційного інструменту CLI та надіслати до відкритого реєстру.
Передумови
- Обізнаність із Solidity та ABI смарт-контрактів
- Розгорнутий смарт-контракт із верифікованим ABI (верифікація на Sourcify (opens in a new tab) є обов'язковою вимогою перед прийняттям дескриптора до реєстру)
- Python 3.12+ для CLI-інструменту перевірки
- Базові знання JSON
Що таке дескриптор ERC-7730?
Дескриптор — це єдиний файл JSON із трьома розділами:
| Розділ | Призначення |
|---|---|
context | Прив'язує дескриптор до конкретних розгортань контракту за ідентифікатором ланцюга (chain ID) та адресою |
metadata | Називає проєкт і визначає константи для багаторазового використання |
display | Зіставляє кожну сигнатуру функції зі зрозумілими для людини мітками та форматами полів |
Оскільки дескриптор відокремлений від самого контракту, ви можете додати підтримку зрозумілого підписання до будь-якого існуючого протоколу без повторного розгортання. Гаманці отримують дескриптори з реєстру та використовують їх під час підписання.
Крок 1: Створіть каркас файлу
Створіть файл із назвою calldata-<contractname>-<descriptorversion>.json. Префікс calldata- вказує реєстру, що цей дескриптор охоплює виклики функцій контракту, на відміну від eip712- для повідомлень із типізованими даними. descriptorversion вказує реєстру версію файлу дескриптора (за замовчуванням 0, якщо версія не вказана).
{
"$schema": "https://eips.ethereum.org/assets/eip-7730/erc7730-v2.schema.json",
"context": {},
"metadata": {},
"display": {
"formats": {}
}
}
Крок 2: Напишіть розділ контексту
Розділ context прив'язує дескриптор до одного або кількох розгортань контракту. Гаманці використовують це, щоб зіставити вхідну транзакцію з правильним дескриптором.
"context": {
"$id": "uniswap-v3-router-mainnet",
"contract": {
"deployments": [
{ "chainId": 1, "address": "0xYourContractAddressOnMainnet" },
{ "chainId": 137, "address": "0xYourContractAddressOnPolygon" }
]
}
}
Поля контексту
context.$id— Унікальний ідентифікатор для цього документа дескриптора або конфігурації розгортання.contract.deployments— Набір розгортань, до яких застосовується цей дескриптор.deployments[].chainId— Ідентифікатор ланцюга EVM (chain ID) для розгортання. Включіть кожен ланцюг, де розгорнуто ваш контракт.deployments[].address— Адреса контракту, яку гаманці повинні асоціювати з цим дескриптором. Використовуйте адресу реалізації, яка містить логіку виконання.
Крок 3: Напишіть розділ метаданих
Розділ метаданих надає зрозумілу для людини інформацію про проєкт і контракт, описані в цьому файлі. Гаманці можуть використовувати цю інформацію для відображення назв протоколів, посилань та інших контекстних деталей під час підписання.
"metadata": {
"owner": "Example Swap Protocol",
"info": { "url": "https://example.xyz" },
"contractName": "SwapRouter"
}
Поля метаданих
owner— Проєкт, протокол, організація або супроводжувач, відповідальний за цей дескриптор.info.url— Канонічна URL-адреса проєкту або документації, яку гаманці можуть показувати користувачам для додаткового контексту.contractName— Назва контракту або реалізації, описана в цьому файлі, яка зазвичай збігається з верифікованим вихідним кодом або ABI.
Якщо ваш файл ERC-7730 описує контракт ERC-20, вам також слід додати об'єкт токена.
Крок 4: Напишіть розділ форматів відображення
Об'єкт display.formats зіставляє сигнатури функцій зі зрозумілими для людини інструкціями щодо підписання. Саме так гаманці показують вашу функцію користувачам перед тим, як вони схвалюють транзакцію!
Кожен ключ — це зрозумілий для людини фрагмент ABI: сигнатура функції, що включає як імена параметрів, так і їхні типи, точно так, як вони вказані у вашому ABI.
Приклад: Опис обміну токенів
"display": {
"formats": {
"swapExactTokensForTokens(uint256 amountIn,uint256 amountOutMin,address[] path,address to,uint256 deadline)": {
"intent": "Swap",
"interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}",
"fields": [
{
"path": "#.amountIn",
"label": "Send",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[0]"
}
},
{
"path": "#.amountOutMin",
"label": "Receive minimum",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[1]"
}
},
{
"path": "#.to",
"label": "Recipient",
"format": "addressName",
"params": {
"types": ["eoa", "contract"],
"sources": ["local", "ens"]
}
},
{
"path": "#.deadline",
"label": "Expires",
"format": "date",
"params": {
"encoding": "timestamp"
}
}
]
}
}
}
Поля відображення
intent— (Обов'язково) Короткий, зручний для користувача опис дії, наприклад, «Обмін» (Swap).interpolatedIntent— (Рекомендовано) Більш розгорнутий шаблон речення, який містить відформатовані значення полів, наприклад"Swap {amountIn} for at least {amountOutMin}". Додайте його разом ізintent, щоб надати ще зручніший дескриптор, який гаманці зможуть відображати з урахуванням будь-яких обмежень екрана.fields— (Обов'язково) Впорядкований список полів транзакції, які гаманці повинні показувати користувачам.-
path— (Обов'язково) Посилання на дані транзакції.#.fieldNameвказує на розкодований параметр даних виклику за іменем в ABI.@.valueстосується значення ETH, надісланого з транзакцією. -
label— (Обов'язково) Зрозуміла для людини мітка, що відображається поруч зі значенням. -
format— (Рекомендовано) Керує тим, як має відображатися значення. Поширені формати включають:tokenAmountaddressNamedate
Використовуйте
raw, коли додаткове форматування не потрібне. Деякі формати приймають додаткову конфігураціюparams. Наприклад:tokenAmountможе використовуватиtokenPathдля визначення того, яка адреса токена надає метадані про десяткові знаки та тикер.dateможе використовуватиencodingдля опису того, як закодована часова мітка.
Якщо вибраний формат не потребує додаткової інформації, пропустіть
params.
-
Повний дескриптор
{
"$schema": "https://eips.ethereum.org/assets/eip-7730/erc7730-v2.schema.json",
"context": {
"$id": "uniswap-v3-router-mainnet",
"contract": {
"deployments": [
{
"chainId": 1,
"address": "0xYourContractAddressOnMainnet"
},
{
"chainId": 137,
"address": "0xYourContractAddressOnPolygon"
}
]
}
},
"metadata": {
"owner": "Example Swap Protocol",
"info": {
"url": "https://example.xyz"
},
"contractName": "SwapRouter"
},
"display": {
"formats": {
"swapExactTokensForTokens(uint256 amountIn,uint256 amountOutMin,address[] path,address to,uint256 deadline)": {
"intent": "Swap",
"interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}",
"fields": [
{
"path": "#.amountIn",
"label": "Send",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[0]"
}
},
{
"path": "#.amountOutMin",
"label": "Receive minimum",
"format": "tokenAmount",
"params": {
"tokenPath": "#.path[1]"
}
},
{
"path": "#.to",
"label": "Recipient",
"format": "addressName",
"params": {
"types": ["eoa", "contract"],
"sources": ["local", "ens"]
}
},
{
"path": "#.deadline",
"label": "Expires",
"format": "date",
"params": {
"encoding": "timestamp"
}
}
]
}
}
}
}
Крок 5: Надішліть до реєстру
Реєстр ERC-7730 (opens in a new tab) — це відкритий репозиторій, який підтримується Фундацією Ethereum як нейтральним розпорядником. Будь-хто може вільно клонувати та самостійно розміщувати його — гаманці незалежно вирішують, яким екземплярам реєстру вони довіряють.
- Зробіть форк репозиторію на GitHub
- Створіть папку за шляхом
registry/<your-project-name>/ - Помістіть свій файл у неї:
registry/myproject/calldata-mycontract-0_0.json - Оновіть поле
$schemaна відносний шлях, що використовується в репозиторії:"../../specs/erc7730-v2.schema.json" - Відкрийте pull request (запит на злиття)
Коли ви відкриваєте PR, CI автоматично запускає перевірку схеми, перевіряє, чи сигнатури функцій створюють дійсні селектори, підтверджує, що адреса контракту верифікована на Sourcify, і позначає невідповідності ABI. Результати перевірки з'являються безпосередньо в PR. Супроводжувачі реєстру перевіряють подання на наявність неправильно сформованих або потенційно шкідливих дескрипторів. Включення до реєстру не означає проведення аудиту або схвалення.
Що відбувається після злиття?
Усі дескриптори в реєстрі відкриті для аудиторів. Після злиття вашого PR будь-який аудитор може перевірити ваш дескриптор і опублікувати криптографічну атестацію (відповідно до ERC-8176 (opens in a new tab)), що підтверджує його точність.
Ці сигнали атестації дозволяють гаманцям застосовувати власні політики довіри — дескриптор із кількома незалежними атестаціями має більшу вагу, ніж той, що їх не має. Ви можете зв'язатися зі спільнотою аудиторів через clearsigning.org (opens in a new tab).
Гаманці самі обирають, який реєстр вони підтримуватимуть. Щойно ваш дескриптор опиниться в реєстрі, гаманці, які підтримують ERC-7730, почнуть отримувати його (якщо він є в їхньому реєстрі) і відображатимуть зрозумілі для людини дані, коли користувачі взаємодіятимуть із вашим контрактом.
Додаткові матеріали
- Специфікація ERC-7730 (opens in a new tab)
- Реєстр ERC-7730 (opens in a new tab)
- clearsigning.org (opens in a new tab) — інструменти, стан екосистеми та управління
- Верифікація контрактів на Sourcify (opens in a new tab)
- Ініціатива Trillion Dollar Security (opens in a new tab)
Останнє оновлення сторінки: 12 травня 2026 р.