﻿---
title: "Декодирование calldata в кошельке"
description: "Ориентированное на проверку руководство по calldata транзакций, словам и смещениям ABI, коллизиям селекторов, прокси, пакетам, разрешениям, permit на основе типизированных данных, симуляции и сверке после транзакции."
image: "https://wiki.fcontext.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.fcontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Декодирование calldata в кошельке

> Только в образовательных целях; не является инвестиционным советом или инвестиционной рекомендацией. Инвестиции могут привести к убыткам.

<a id="answer"></a>

## Краткий ответ

Calldata — неизменяемая строка байтов, передаваемая на вход транзакции Ethereum верхнего уровня или внутреннего вызова сообщения. Обычный вызов функции Solidity начинается с селектора `4-byte`, за которым следуют аргументы в кодировке ABI. Однако calldata не является самоописываемой: одни и те же байты могут означать разное для различного исполняемого кода, реализаций прокси или схем. Функции fallback, низкоуровневый ассемблер и протоколы не на Solidity вообще не обязаны следовать стандартному ABI функций.

Поэтому кошелёк должен показывать больше, чем предполагаемое имя функции. Безопасная проверка связывает байты с `chainId`, блоком, `from`, `to`, нативным `value`, `codeHash` исполняемого кода, активной реализацией и доверенным ABI; строго декодирует каждый вложенный вызов; отличает calldata в сети от подписей EIP-712; симулирует в явно заданном состоянии; а после включения сверяет фактическую квитанцию и изменения состояния.

<a id="mechanism"></a>

## Как это работает

1. Зафиксируйте конверт подписи и точку наблюдения: `chainId`, номер и хеш блока, `from`, `to`, нативное `value`, входные байты, nonce и поля комиссии. Сохраните источник данных кошелька или RPC: декодированная нагрузка из другой сети или другого блока подтверждает уже не то же самое.
2. Перед декодированием определите тип объекта. Транзакция, запрос типизированных данных EIP-712, permit ERC-2612, UserOperation ERC-4337 и обычное personal-sign сообщение используют разные домены и схемы; нельзя принудительно пропускать их все через ABI транзакций.
3. Определите цель на зафиксированном блоке. Прочитайте исполняемый байткод и `codeHash`; при необходимости выявите прокси, beacon или реализацию; запишите слоты реализации и администратора; получите ABI именно для этой версии кода. Реестр селекторов предлагает варианты, но не является доказательством.
4. Декодируйте строго. Селектор — первые `4 bytes` Keccak-256 от канонической сигнатуры функции без типов возвращаемых значений. Статические значения занимают слова по `32-byte`, а заголовки динамических значений содержат смещения от блока аргументов после селектора. Отклоняйте усечённые данные, смещения за границами, невозможные длины, некорректное дополнение и необъяснимые конечные байты.
5. Рекурсивно раскройте multicall, вложенную calldata и делегированное выполнение. Для каждого дочернего вызова укажите цель, нативную стоимость, селектор, аргументы, тип вызова и флаг `allowFailure`, если он есть. При `delegatecall` код реализации выполняется в контексте адреса, баланса и хранилища вызывающего контракта, а `msg.sender` и `msg.value` сохраняются.
6. Создайте отдельные реестры полномочий и стоимости, затем выполните симуляцию. Запишите получателей, операторов расходов, операторов NFT, сырые единицы токенов, десятичность, сроки, пределы проскальзывания и нативную стоимость. Симулируйте с точным блоком, отправителем и стоимостью, но считайте результат условным снимком: состояние, цены, время, код и порядок транзакций могут измениться.
7. До подписи подтвердите каждое существенное поле. После включения проверьте статус квитанции, события, трассы при наличии, а также изменения балансов, разрешений и статуса операторов; отличайте перехваченные ошибки дочерних вызовов от успеха верхнего уровня; учитывайте gas даже при откате; дождитесь требуемой финальности; при необъяснимой ошибке остановитесь, а не подписывайте вслепую повторно.

<a id="example"></a>

## Разобранные примеры

- **Статический перевод ERC-20.** `transfer(address,uint256)` обычно использует селектор `0xa9059cbb`. Один селектор и два слова ABI занимают `4 + 2 * 32 = 68 bytes`. Сырое значение `1,500,000` для токена, у которого независимо подтверждено `6 decimals`, отображается как `1.5 tokens`. Число десятичных знаков — внешние метаданные контракта, в аргументах оно не закодировано; один селектор не определяет контракт или функцию однозначно.
- **Смещение динамических байтов.** Для `f(address,bytes)` с нагрузкой `3-byte` заголовок из двух слов занимает `64 bytes`. Динамическое смещение равно `0x40` и отсчитывается от начала блока аргументов без селектора. Хвост содержит слово длины `32-byte` и дополненное слово данных `32-byte`, поэтому общий размер calldata равен `4 + 64 + 32 + 32 = 132 bytes`. Если ошибочно считать смещение абсолютным от нулевого байта, адрес окажется на четыре байта дальше.
- **Стоимость пакета зависит от реализации.** Внешний вызов передаёт `1.00 ETH`; три декодированных дочерних вызова явно требуют `0.20 ETH`, `0.30 ETH` и `0.10 ETH`, всего `0.60 ETH`. Оставшиеся `0.40 ETH` код пакета может вернуть, удержать, переслать или из-за них откатиться. Если третий вызов завершается ошибкой при `allowFailure=true`, предыдущие могут остаться исполненными; атомарная реализация может откатить всё.
- **Permit во время подписи — не calldata ретранслятора.** Владелец с `1,000 USDC` подписывает permit ERC-2612 на `300 USDC` при nonce `41`. Одна подпись не меняет ни баланс, ни разрешение. После успешной отправки ретранслятором nonce становится `42`, а разрешение — `300`; после расходования `180` баланс равен `820`, остаток разрешения — `120`. Отключение сайта не отзывает полномочие.

<a id="risks"></a>

## Риски

- Декодирование для неверной сети, развилки, метки блока или конверта транзакции.
- Подпись для поддельного домена, целевого адреса или получателя.
- Ошибочное предположение об уникальности селектора `4-byte` при возможных коллизиях.
- Использование предполагаемого, устаревшего или неверно проверенного ABI.
- Доверие метке проверенного исходного кода без сверки с текущим `codeHash`.
- Пропуск смены реализации, beacon или администратора между проверкой и выполнением.
- Игнорирование функции прокси, чей селектор конфликтует с реализацией.
- Непонимание того, что `delegatecall` записывает в хранилище вызывающего контракта.
- Принятие некорректных динамических смещений, длин, дополнения или конечных байтов.
- Нераскрытый вложенный пакет, скрывающий цели, стоимость или полномочия.
- Предположение об атомарности, когда реализация перехватывает или допускает ошибки дочерних вызовов.
- Игнорирование нативного `value` верхнего уровня из-за безобидного вида аргументов токена.
- Неверная десятичность или предположение, что токены с комиссией за перевод и ребейзингом стандартны.
- Неограниченное разрешение ERC-20 или неверная обработка гонки при его изменении.
- Игнорирование того, что NFT `setApprovalForAll` распространяется на всю коллекцию.
- Принятие типизированных данных EIP-712 или permit ERC-2612 за calldata транзакции.
- Пропуск nonce, срока, проверяющего контракта, домена сети или границ защиты от повтора.
- Доверие симуляции вопреки изменениям oracle, времени, ожидающего состояния, MEV или кода.
- Принятие статуса квитанции, событий или трасс провайдера за полное доказательство экономического состояния.
- Слепая повторная подпись через скомпрометированный интерфейс или игнорирование включения, реорганизации и финальности.

<a id="misconceptions"></a>

## Распространённые заблуждения

- Селектор функции однозначно определяет, что исполнит контракт.
- Сводка проверенного интерфейса совпадает с подписываемыми байтами и текущей реализацией.
- Транзакция с `value=0` не может перемещать токены, NFT или делегированные активы.
- Успех симуляции или квитанции доказывает безопасность и ожидаемый экономический результат.
- Отключение dapp отзывает разрешения, permit и полномочия операторов NFT.

<a id="related"></a>

## Связанные темы

- [Симуляция транзакций](/ru/crypto/transaction-simulation/)
- [Разрешения кошелька](/ru/crypto/wallet-approval/)
- [Подпись кошелька](/ru/crypto/wallet-signature/)

<a id="sources"></a>

## Источники

- [Contract ABI Specification](https://docs.soliditylang.org/en/latest/abi-spec.html) - Solidity Documentation (дата обращения: 2026-08-12)
- [Introduction to Smart Contracts](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#delegatecall-and-libraries) - Solidity Documentation (дата обращения: 2026-08-12)
- [Transactions](https://ethereum.org/developers/docs/transactions/) - Ethereum.org (дата обращения: 2026-08-12)
- [ERC-20: Token Standard](https://eips.ethereum.org/EIPS/eip-20) - Ethereum Improvement Proposals (дата обращения: 2026-08-12)
- [EIP-712: Typed structured data hashing and signing](https://eips.ethereum.org/EIPS/eip-712) - Ethereum Improvement Proposals (дата обращения: 2026-08-12)
- [ERC-2612: Permit Extension for EIP-20 Signed Approvals](https://eips.ethereum.org/EIPS/eip-2612) - Ethereum Improvement Proposals (дата обращения: 2026-08-12)
- [ERC-721: Non-Fungible Token Standard](https://eips.ethereum.org/EIPS/eip-721) - Ethereum Improvement Proposals (дата обращения: 2026-08-12)
- [ERC-1967: Proxy Storage Slots](https://eips.ethereum.org/EIPS/eip-1967) - Ethereum Improvement Proposals (дата обращения: 2026-08-12)

Source: https://wiki.fcontext.com/ru/crypto/calldata-decoding-wallet/index.mdx
