Интеграция EIP-1271 (верификация подписей контрактов)
Стандартная проверка подписи в Solidity работает через ecrecover: берём хэш сообщения, подпись, восстанавливаем адрес подписавшего, сравниваем с ожидаемым. Это работает для EOA (Externally Owned Accounts) — обычных кошельков с приватным ключом. Но мультисиг Gnosis Safe — это контракт. Контракты не имеют приватного ключа, не могут подписывать через ECDSA, и ecrecover для них не применимо. EIP-1271 решает это: стандарт, который позволяет контрактам объявлять «да, я считаю эту подпись действительной».
Как работает EIP-1271
Интерфейс максимально простой:
interface IERC1271 {
function isValidSignature(bytes32 hash, bytes memory signature)
external view returns (bytes4 magicValue);
}
Если контракт возвращает 0x1626ba7e (magic value EIP-1271) — подпись признана валидной. Любое другое значение или revert — невалидна.
Верификатор (ваш контракт, который принимает подписи) должен проверять: является ли адрес подписавшего EOA или контрактом. Если контракт — вызывать isValidSignature вместо ecrecover. Это именно то, что реализует SignatureChecker из OpenZeppelin:
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
bool valid = SignatureChecker.isValidSignatureNow(signer, hash, signature);
isValidSignatureNow автоматически определяет тип аккаунта и применяет нужный метод верификации. Единственный вызов покрывает и EOA и контракты.
Где EIP-1271 критичен
Gnosis Safe как signer. Компании и DAOs держат средства на мультисиг-кошельках. Если ваш протокол не поддерживает EIP-1271, Gnosis Safe не может быть авторизованным подписантом — только EOA. Это исключает корпоративных и DAO-клиентов.
Account Abstraction (EIP-4337). Смарт-кошельки в AA-экосистеме (Biconomy, ZeroDev, Safe{Core}) реализуют EIP-1271 как основной механизм верификации. dApps, которые проверяют подписи только через ecrecover, несовместимы с AA-кошельками.
EIP-712 + permit. Протоколы, использующие permit (ERC-2612), должны поддерживать EIP-1271 для permit-подписей от контрактов. Иначе мультисиг не может выдать permit — только напрямую вызвать approve.
Orderbook-протоколы. OpenSea Seaport, 0x Protocol, CoW Protocol — все используют подписанные ордера. EIP-1271 позволяет контрактам размещать ордера без on-chain транзакции при каждом листинге.
Типичные ошибки при реализации
Проверка только через ecrecover. Самая частая: разработчик пишет require(ecrecover(hash, v, r, s) == signer) и не задумывается о контрактных кошельках. Сломано для Safe, сломано для AA.
Отсутствие проверки на revert. isValidSignature может сделать revert (контракт не реализует интерфейс, исчерпан газ, контракт не задеплоен). Вызов без try/catch или low-level call — ваш верификатор упадёт вместе с ним.
Replay attacks. EIP-1271 не определяет формат hash — это ответственность разработчика. Подпись должна включать chainId, адрес контракта, nonce или timestamp. Без этого подпись, действительная для одного контракта/сети, действительна для другого. Используйте EIP-712 для структурированного хэширования.
Бесконечная рекурсия. Контракт A вызывает isValidSignature контракта B, который вызывает isValidSignature контракта A. Теоретически возможно при неправильной архитектуре. Ограничение глубины через gas limit спасает от бесконечной рекурсии, но транзакция упадёт с out of gas вместо внятной ошибки.
Интеграция в существующий протокол
Если протокол уже использует ecrecover, миграция на EIP-1271 минимальна: заменить прямой вызов ecrecover на SignatureChecker.isValidSignatureNow. Функция обратно совместима — для EOA поведение идентично.
Для протоколов с подписанными офф-чейн сообщениями (permit, meta-transactions, gasless relay) — добавить EIP-712 типизацию если ещё нет, проверить что hash включает защиту от replay.
Интеграция EIP-1271 в существующий протокол — 1-3 дня: аудит текущей логики подписей, замена проверок, тесты с Gnosis Safe, тесты с EOA (регрессия). Для новых систем — закладывается изначально, не добавляет значимых сроков.







