Search code examples
pythonethereumweb3py

How to build transaction payload for signed EIP-1559 transaction


I am trying to construct the raw transaction data based on a signed EIP-1559 transaction according to the EIP-1559 spec. However, it is not matching the value returned by web3py when signing a transaction. Below is a script I used to recreate the issue.

compute_raw_tx.py:

from web3 import Web3
import rlp    

w3 = Web3(Web3.HTTPProvider(NODE_URL))

tx = {
    'from': PUBLIC_KEY,
    'nonce': w3.eth.get_transaction_count(PUBLIC_KEY),
    'to': '0x0000000000000000000000000000000000000000',
    'value': Web3.toWei(0.01, 'ether'),
    'chainId': 5,
    'gas': 50000,
    'maxFeePerGas': Web3.toWei(500, 'gwei'),
    'maxPriorityFeePerGas': Web3.toWei(200, 'gwei'),
    'data': '0x0'
}

signed_tx = w3.eth.account.sign_transaction(tx, PRIVATE_KEY)

print(signed_tx)

encoded = rlp.encode([
    hex(tx['chainId']),
    hex(tx['nonce']),
    hex(tx['maxPriorityFeePerGas']),
    hex(tx['maxFeePerGas']),
    hex(tx['gas']),
    tx['to'],
    hex(tx['value']),
    tx['data'],
    [],
    hex(signed_tx['v']),
    hex(signed_tx['r']),
    hex(signed_tx['s'])
])

print(f'0x02{encoded.hex()}')

Solution

  • According to this post, I didn't quite have the correct types for all the values. Here is the working solution:

    encoded = rlp.encode([
            tx['chainId'],
            tx['nonce'],
            tx['maxPriorityFeePerGas'],
            tx['maxFeePerGas'],
            tx['gas'],
            to_bytes(hexstr=tx["to"]),
            tx['value'],
            HexBytes(tx['data']),
            [],
            signed_tx['v'],
            HexBytes(signed_tx['r']),
            HexBytes(signed_tx['s'])
        ])
    
        reconstructed_raw_transaction = f'0x02{encoded.hex()}'