Безопасность и бэкапы

Декодер input data транзакции (calldata)

Когда dApp просит кошелёк подтвердить взаимодействие с контрактом, настоящая инструкция — это input data: 4-байтный селектор функции и параметры по 32 байта. Кошельки расшифровывают его не всегда, и дрейнеры на это рассчитывают. Вставьте hex из вкладки данных кошелька или из обозревателя и увидите функцию, spender или получателя, сумму и то, выдаётся ли безлимитное разрешение.

Сумма нативной монеты (ETH, BNB…) — отдельное поле транзакции, в calldata её нет.

Как устроена calldata

Первые четыре байта — селектор: первые 4 байта хеша Keccak-256 от сигнатуры функции. transfer(address,uint256) превращается в a9059cbb, approve(address,uint256) — в 095ea7b3. Дальше идут аргументы в кодировке ABI, каждый дополнен до 32 байт: адрес занимает последние 20 байт своего слова, число — 256-битное беззнаковое целое, динамическое значение вроде bytes[] хранится как смещение до места, где начинаются его длина и содержимое.

Суммы токенов — сырые целые числа без десятичных знаков. 25000000 для USDT в Ethereum — это 25 USDT, потому что у токена 6 знаков; то же число у токена с 18 знаками — крошечная доля. Сам токен — это контракт, который вы вызываете (поле 'to' транзакции), а не параметр.

calldata = селектор(4 байта) ‖ арг1(32 байта) ‖ арг2(32 байта) ‖ … селектор = keccak256("approve(address,uint256)")[0..4] = 0x095ea7b3

Вызовы, на которые стоит посмотреть дважды

  • approve с суммой 2²⁵⁶−1 (выглядит как ffff…ffff) — безлимитное разрешение. Spender может в любой момент забрать весь баланс этого токена, пока вы не отзовёте разрешение.
  • setApprovalForAll(operator, true) — отдаёт оператору все NFT коллекции. Маркетплейсы просят его при выставлении на продажу; случайный сайт с таким запросом — классический NFT-дрейнер.
  • permit(owner, spender, value, deadline, v, r, s) — отправляет в сеть офчейн-подпись. Разрешение было выдано в момент подписи сообщения, часто раньше и на другом сайте.
  • transferFrom(from, to, amount) — перемещает токены с адреса 'from' по существующему разрешению. Если 'from' — ваш адрес и перевод начинали не вы, остановитесь.
  • multicall(bytes[]) — пакет вызовов. Роутеры законно используют его для обменов; здесь каждый вложенный вызов расшифровывается отдельно.

Где взять input data

Большинство кошельков показывают его на экране подтверждения во вкладке «Данные», Hex или «Подробнее». В обозревателях типа Etherscan это поле Input Data транзакции; переключите вид на Original, чтобы скопировать hex. Аппаратные кошельки показывают расшифрованные поля для поддерживаемых контрактов и хеш для неизвестных — если виден только хеш, включён blind signing и вы доверяете экрану компьютера.

Инструменту не нужно ничего секретного, и он не обращается к нодам: он читает вставленный hex. Неизвестный селектор — не доказательство опасности, но повод прочитать проверенный исходный код контракта до подписи.

Частые вопросы

+Что значит безлимитное разрешение?

Контракт может перевести любую сумму этого токена из вашего кошелька — сейчас и в будущем — без нового запроса. Отзывайте ненужные разрешения в кошельке или через сервис отзыва.

+approve(spender, 0) опасен?

Нет. Нулевое разрешение отзывает прежнее. Проверьте, что токен и spender — те, что вы хотите отозвать.

+Почему не видна сумма ETH?

Сумма нативной монеты — отдельное поле транзакции ('value'). Calldata описывает только функцию контракта и её аргументы.

+Селектор неизвестен. Это мошенничество?

Не обязательно: функций миллионы. Откройте контракт в обозревателе, убедитесь, что код проверен, и прочитайте, что делает функция, — или не подписывайте.

+Можно вставить хеш транзакции?

Нет, хеш лишь обозначает транзакцию. Откройте её в обозревателе и скопируйте hex из Input Data.

Все расчёты выполняются в вашем браузере, введённые данные не отправляются на KOT.CASH. Результаты — оценка для информации, а не финансовая, налоговая или юридическая консультация.

← Все крипто-инструменты (92)

Декодер input data транзакции: читаем calldata