EIP-712 превращает непрозрачный набор байтов в типизированные поля, которые кошелёк может показать человеку. Такая подпись часто используется для входа, размещения ордера, голосования, разрешения на токены и выполнения операции через relayer. Она не отправляет обычную on-chain транзакцию в момент подтверждения, но её последствия могут быть финансовыми.
Безопасная проверка строится не вокруг названия сайта, а вокруг того, что именно подписывается: для какой сети, какого verifying contract, какого действия, актива, получателя, суммы и срока. Если кошелёк скрывает эти поля или показывает только хеш, смысл подписи нельзя считать проверенным.
Чем EIP-712 отличается от транзакции
Транзакция Ethereum содержит получателя, value, calldata, gas и nonce отправителя, а после отправки попадает в сеть. EIP-712 создаёт подпись структурированного сообщения вне блокчейна. Эту подпись позднее может проверить смарт-контракт, сервер или другой участник.
Подписывающий обычно не платит gas в момент подписи. Это не делает действие безвредным. Если сообщение является Permit, торговым ордером или авторизацией, другой адрес может передать его контракту и изменить состояние. Общее различие между сообщением и транзакцией подробно разобрано в материале о подписи в криптокошельке.
Из каких частей состоит EIP-712
Сообщение включает описание типов, основной тип, домен и конкретные значения. Стандарт строит хеш структуры и соединяет его с domain separator. Кошелёк подписывает итоговый хеш приватным ключом, а проверяющая сторона восстанавливает адрес подписанта.
Домен отделяет подпись одного приложения и контракта от другого. В нём могут присутствовать:
- name – название домена, которое задал разработчик;
- version – версия схемы;
- chainId – идентификатор сети;
- verifyingContract – контракт, который должен принять подпись;
- salt – дополнительный разделитель.
Сам EIP-712 не добавляет универсальную защиту от повторного применения. Безопасность replay зависит от полей конкретного сообщения, например nonce, deadline, chainId и логики verifying contract.
Проверка перед подписью
- Остановитесь и определите ожидаемое действие. Если вы нажали «войти», но кошелёк показывает Permit, Permit2, Order, Transfer или Delegation, запрос не соответствует цели.
- Проверьте активную сеть и chainId. Они должны совпадать с сетью приложения. Значение 0 или отсутствие понятной привязки повышает риск повторного использования в другой сети, если контракт не добавляет собственную защиту.
- Проверьте verifyingContract. Сравнивать нужно полный адрес с контрактом, который действительно использует приложение. Название домена легко скопировать, адрес – фактическая граница проверки.
- Найдите основной тип сообщения. Permit, PermitSingle, PermitBatch, Order, Vote и Login означают разные полномочия. Красивое описание интерфейса не заменяет тип.
- Проверьте адрес получателя прав. Поле может называться spender, operator, delegate, recipient или executor. Неизвестный адрес нельзя считать безопасным только потому, что запрос появился на знакомой странице.
- Проверьте актив и сумму. Убедитесь, что token или asset соответствует выбранному токену. Безлимитное значение фактически даёт доступ ко всему текущему и будущему балансу в пределах разрешения.
- Проверьте nonce. Он должен предотвращать повторное применение уже использованной подписи. Не нужно угадывать правильное число, но отсутствие nonce в финансовой авторизации требует объяснимой защиты в контракте.
- Проверьте deadline или expiry. Слишком далёкий срок увеличивает окно атаки. Нулевое или максимальное значение может означать отсутствие практического ограничения.
- Проверьте дополнительные условия. Для ордера это цена, объём, сторона сделки, получатель и комиссия. Для голосования – proposal и choice. Для сессии – методы, лимиты и разрешённые контракты.
- Подтверждайте только при полном совпадении. Если хотя бы одно критичное поле непонятно, отклоните запрос, закройте вкладку и заново откройте сервис из сохранённого адреса.
Как проверить контракт без доверия к интерфейсу
Скопируйте verifyingContract из окна кошелька и найдите его во встроенном обозревателе сети или в обозревателе, которому вы доверяете. Проверьте, верифицирован ли код, как называется контракт, является ли адрес proxy и кто может обновлять реализацию. Совпадение первых и последних символов недостаточно – вредоносный адрес может выглядеть похоже.
Если приложение публикует адреса в собственной документации, открывайте её независимо, а не по ссылке из подозрительного сообщения. Для proxy важно проверять не только оболочку, но и текущую implementation. Даже официально развёрнутый контракт может иметь широкие возможности, поэтому назначение метода всё равно нужно понимать.
Permit, Permit2 и токенные разрешения
ERC-2612 Permit позволяет владельцу токена подписать allowance для spender. Контракт токена проверяет подпись и устанавливает разрешение без отдельной approve-транзакции владельца. Критические поля – owner, spender, value, nonce и deadline.
Permit2 использует отдельный универсальный контракт и может управлять разрешениями для многих токенов. В сообщении встречаются token, amount, expiration, nonce, spender и sigDeadline. Подробная механика описана в разборе Permit и Permit2. Опаснее всего сочетание неизвестного spender, большой суммы и долгого срока.
После использования подписи on-chain разрешение может продолжать действовать. Отключение сайта от кошелька его не отзывает. Нужно отдельно уменьшить allowance или использовать функцию отмены, если она предусмотрена контрактом.
Признаки опасного запроса
- Сайт обещает airdrop или срочное спасение средств и торопит подписать сообщение.
- Кошелёк не декодирует поля и показывает слепую подпись или неизвестный хеш.
- Название домена знакомое, но verifyingContract не совпадает с ожидаемым.
- Запрос на вход содержит spender, token, amount, operator или transfer details.
- Сумма максимальная, срок не ограничен, а получатель прав неизвестен.
- Одно действие вызывает несколько разных подписей без понятного объяснения.
- Домен открыт из рекламного объявления, личного сообщения или похожего адреса.
Так работают многие crypto drainer: они не обязаны красть seed-фразу, если пользователь сам выдаёт действительное разрешение. Антивирус и аппаратный кошелёк не исправят смысл уже подтверждённой подписи.
Если кошелёк показывает не все поля
Не переносите запрос в другой кошелёк только ради кнопки подтверждения. Отсутствие декодирования означает, что интерфейс не даёт достаточно информации. Для значимой суммы безопаснее отказаться и проверить действие на отдельном адресе с минимальным балансом.
Аппаратный кошелёк может подтвердить криптографическую подпись, но маленький экран не всегда показывает всю структуру. Если устройство сообщает blind signing, пользователь фактически доверяет компьютеру подготовить корректные данные. Для EIP-712 это особенно опасно, поскольку одна подпись может стать исполнимым разрешением.
Что делать после случайной подписи
Сначала отключите подозрительное приложение, но не считайте это отзывом полномочий. Проверьте allowance и operator approvals в затронутой сети, отмените их и изучите историю адреса. Если подпись могла создать ордер, Permit или сессию, используйте предусмотренный протоколом cancel, invalidate nonce или revoke.
При признаках активного вывода перенесите оставшиеся активы на новый адрес с чистого устройства. Не отправляйте дополнительный gas на потенциально скомпрометированный адрес без плана: автоматический бот может забрать его. Сессионные разрешения и их ограничения разобраны отдельно в материале о сессионных ключах dapp.
Короткий контрольный список
- Действие совпадает с тем, что вы начали в приложении.
- Сеть и chainId верны.
- Полный verifyingContract проверен независимо.
- Primary type понятен.
- Spender, operator или recipient ожидаемы.
- Токен, сумма и направление операции верны.
- Nonce присутствует там, где подпись должна быть одноразовой.
- Deadline разумно ограничен.
- Кошелёк показывает структуру без blind signing.
Итог
EIP-712 улучшает читаемость подписи, но не определяет, безопасно ли её содержание. Проверять нужно домен, chainId, verifyingContract и все поля действия. Особенно опасны неизвестный spender, безлимитная сумма, долгий срок и подпись, не соответствующая ожидаемой операции. Если кошелёк не позволяет понять смысл сообщения, правильное действие – отклонить запрос.



