Ошибка Invalid Sender при отправке криптовалюты через Web3 PHP

    При разработке платёжного модуля на PHP с библиотекой Web3 часто возникает ошибка invalid sender. Это значит, что сеть не может верифицировать отправителя транзакции. В большинстве случаев проблема не в приватном ключе, а в неправильном формировании подписи или параметров транзакции. Ниже мы пошагово разберём типичные причины и способы их устранения.

    Почему возникает invalid sender?

    Ошибка invalid sender в Ethereum и совместимых сетях (Polygon, BSC) появляется, когда:

    • Неверно рассчитан nonce (счётчик транзакций адреса);
    • Некорректно подписан raw-транзакция - не совпадает chain ID или формат подписи;
    • Используется неправильный приватный ключ или формат ключа (без префикса 0x);
    • Ошибка в расчёте gas limit или gas price (слишком низкое значение).

    Поскольку на Node.js та же логика работает, ищем баг именно в PHP-коде.

    Шаг 1: Проверьте nonce

    Nonce должен быть точным количеством исходящих транзакций с кошелька. В вашем коде nonce получается через getTransactionCount с параметром pending. Это корректно, но убедитесь, что callback возвращает строку, а не объект BigNumber. Используйте toString() - как в примере. Если nonce на единицу больше или меньше - транзакция будет отклонена.

    Шаг 2: Chain ID - частая ошибка в PHP

    В Ethereum-транзакциях после EIP-155 обязательно указывается chain ID. В вашем коде chain ID не передаётся в конструктор Transaction. Для Polygon Mumbai (chain ID 80001) нужно явно указать четвёртый параметр:

    $transaction = new \kornrunner\Ethereum\Transaction(
        dechex($nonce),
        dechex($gasPrice),
        dechex($gasLimit),
        env('CONTRACT_ADDRESS'),
        dechex('0'),
        $data,
        80001  // chain ID
    );

    Без chain ID подпись считается невалидной - сеть видит invalid sender.

    Шаг 3: Формат приватного ключа

    Убедитесь, что WALLET_PRIVATE_KEY в .env не содержит префикса 0x. Библиотека kornrunner/ethereum-tx ожидает чистую hex-строку (64 символа). Если ключ с префиксом - удалите его или обрежьте через substr.

    Шаг 4: Gas limit для токенов ERC-20

    Вызов estimateGas для метода transfer токена может вернуть значение, которого недостаточно для выполнения транзакции на стороне сети. Добавьте запас хотя бы 10-20% к полученному gas limit:

    $gasLimit = bcadd($res->toString(), '20000'); // добавить 20000 газа

    Слишком низкий gas limit приводит к падению транзакции с разными ошибками, включая invalid sender.

    Шаг 5: Проверьте адрес назначения и контракта

    Убедитесь, что $to и CONTRACT_ADDRESS передаются в нижнем регистре (checksum-адреса могут не поддерживаться библиотекой). Приведите их к lowercase через strtolower.

    Итог: что исправить в коде

    • Добавить chain ID (80001 для Polygon Mumbai) в конструктор Transaction;
    • Убрать префикс 0x из приватного ключа;
    • Добавить запас gas limit (+20000);
    • Привести адреса к нижнему регистру;
    • Проверить, что nonce получен корректно (проверьте лог перед отправкой).

    После этих изменений транзакция должна уйти без ошибки invalid sender. Если проблема остаётся - проверьте версии библиотек: web3p/web3.php и kornrunner/ethereum-tx должны быть обновлены до последних.

    Часто задаваемые вопросы