amashukov/abi-encoder-php

Solidity ABI calldata encoder in pure PHP — function selectors plus static (address/uint/int/bytesN) and dynamic (string/bytes) types, byte-for-byte equivalent to ethers.js v6.

Maintainers

Package info

github.com/AndreyMashukov/abi-encoder-php

pkg:composer/amashukov/abi-encoder-php

Statistics

Installs: 95

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-05-24 05:30 UTC

This package is auto-updated.

Last update: 2026-05-24 12:41:08 UTC


README

Solidity ABI calldata encoder in pure PHP — byte-for-byte parity with ethers.js v6.

CI PHPStan L9 Latest Version Downloads PHP License Stars

Encode Ethereum / EVM Solidity ABI calldata in pure PHP: function selectors (methodId), static head types (address, uint8 / uint24 / uint256) and top-level dynamic types (bytes, string). Output is byte-for-byte equivalent to ethers.js v6 Interface.encodeFunctionData, so calldata built in PHP matches what your JavaScript tooling and Solidity contracts expect.

Features

  • Function selector (methodId) from a canonical signature via keccak-256.
  • Full call encoding (selector + head + dynamic tail) in one call.
  • Component encoders: encodeAddress, encodeUint, encodeBytes.
  • Bigint-safe uint256 via ext-gmp — accepts hex or decimal strings, handles max uint256.
  • Byte-for-byte parity with ethers.js v6 (cross-validated in tests).
  • PHPStan level 9 clean, strict_types.

Why amashukov/abi-encoder-php

Most PHP web3 stacks pull in web3p/web3.php (and its web3p/ethereum-abi) for ABI encoding, which is a much larger surface than a contract call usually needs. This package is intentionally narrow and dependency-light: it covers the head-only static types and top-level dynamic bytes / string that real EVM contract calls use, with explicit ethers.js v6 parity as the correctness bar. If you only need to build calldata for eth_sendRawTransaction, this is the focused tool.

Installation

composer require amashukov/abi-encoder-php

Usage

Function selector

use Amashukov\AbiEncoder\AbiEncoder;

AbiEncoder::methodId('withdraw(address,uint256)');   // 'f3fef3a3'

The selector is the first 4 bytes of the keccak-256 hash of the canonical signature, returned as 8 hex chars (no 0x).

Encode a full call

$calldata = AbiEncoder::encodeCall('withdraw(address,uint256)', [
    ['address', '0x1234567890123456789012345678901234567890'],
    ['uint256', '500000000000000000'],   // decimal string; bigints supported via ext-gmp
]);
// 0xf3fef3a3000000…0006f05b59d3b20000

Each argument is a [type, value] pair. Supported types: address, uint8, uint24, uint256, bytes, string. Dynamic types (bytes, string) are placed in the tail with the correct head offset, exactly as the ABI spec + ethers.js produce.

Encode individual components

AbiEncoder::encodeAddress('0xABCDEF…');         // left-padded to 32 bytes, lowercased
AbiEncoder::encodeUint('0xFF');                 // accepts hex or decimal; bigint-safe
AbiEncoder::encodeUint('115792089237316195423570985008687907853269984665640564039457584007913129639935'); // max uint256
AbiEncoder::encodeBytes('0xdeadbeef');          // length word + right-padded data
AbiEncoder::encodeBytes('v1', isString: true);  // UTF-8 string as dynamic bytes

Scope

Intentionally narrow — covers the head-only static types and top-level dynamic bytes / string that real EVM contract calls use. Nested dynamic types (bytes[], string[], dynamic tuples) are out of scope.

Requirements

Related packages

Package Tier Purpose
amashukov/keccak-php leaf keccak-256 hashing (selector hash)
amashukov/eip1559-tx-signer-php composite EIP-1559 raw tx assembly + signing
amashukov/rlp-php leaf RLP encoding
amashukov/secp256k1-php leaf ECDSA sign / pubkey derivation
amashukov/eth-rpc-client-php RPC Ethereum JSON-RPC client
amashukov/eth-php meta EVM umbrella package

Quality

  • PHPStan level 9.
  • php-cs-fixer with the @PER-CS ruleset.
  • GitHub Actions CI on every push.
  • Byte-for-byte parity tests against ethers.js v6 Interface.encodeFunctionData.

License

MIT.