Ethereum is a popular public blockchain that enables you to create decentralized applications across a variety of use cases. In 2020 and 2021, it became widely used for decentralized finance (DeFi) apps and non-fungible token (NFT) apps. Due to its permissionless nature, it’s available to every user by just setting up an Ethereum account. These Ethereum accounts consist of a private key and a public key. The associated Ethereum public address is derived from the public key.

One of the challenges to interacting as a user with a public blockchain such as Ethereum is safely managing the private key. For a given Ethereum address, a user can transfer their funds and assets or trigger other sensitive operations by signing transactions with the corresponding private key. Therefore, the private key material must be carefully safeguarded against loss, theft, and malicious attackers.

Fully decentralized applications typically expect the users to manage their Ethereum accounts and transactions on their own.

However, for a certain type of application, it may be desirable to entrust the management of key material to an external process or service, such as when the key material is frequently accessed by automated operations. This is a common requirement for operations like minting on NFT platforms, or deposit and withdraw operations on exchanges.

This post is based on the two-post series detailing how to use AWS Key Management Service (AWS KMS) to securely manage Ethereum accounts. For all further references to the first or the second part of the series, we refer to Part 1 and Part 2.

The previous two posts explained the following:

In this post, we guide you through the Ethereum Improvement Proposal (EIP) 1559 (EIP-1559), its user experience (UX) implications, the changes in the protocol, and how to use it with AWS KMS. This post is based on the two previous posts. It’s highly recommended to read these posts first because they give a detailed introduction to Ethereum transactions, the related elliptic curve cryptography, and the required AWS services and general infrastructure.

This post discusses the following:

  • What is EIP-1559
  • How are EIP-1559 transactions different from legacy transactions
  • How to create a valid EIP-1559 Ethereum transaction using AWS KMS and Lambda and make it portable

What is EIP-1559?

The Ethereum Improvement Proposal (EIP) 1559 is a major reform to the mechanics of the transaction fee market of the Ethereum blockchain protocol. In short, as stated in the Motivation section of EIP-1559, it’s about fixing the historic auction mechanism, where users send transactions with bids, (gas prices) and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify.

The auction mechanism previously used for legacy and EIP-155 transactions leads to multiple sources of inefficiencies. For the end-users, this results in a poor UX by overpaying gas costs for transactions and the uncertainty if and when their transactions go through.

Therefore, one of the main benefits of the proposal is better UX for end-users. Furthermore, it provides economic benefits (for example, by the deflationary pressure of burning ETH), and security benefits (such as by making DOS and spam attacks more costly over time). For more information, see Why 1559?

The conceptual research on how to improve the fee market of Ethereum was started by Vitalik Buterin in 2018. This led to the development of EIP-1559 from 2019 until 2021 by the Ethereum community. On August 5, 2021, the long-awaited EIP-1559 update to the fee market launched as part of Ethereum’s London network upgrade. Polygon, an Ethereum Virtual Machine (EVM)-compatible Ethereum sidechain, went live with EIP-1559 on their mainnet on January 18, 2022.

On a high level, with EIP-1559, the fee marketplace for transactions has been changed in multiple ways:

  • It moves from a first-price auction with a single gas price bid to a hybrid system that involves a base fee and tips (also called a priority fee).
  • It moves from a fixed block size to a flexible block size that expands and contracts based on demand. However, it has a maximum block gas limit of 30 million gas.
  • It moves from a “fees are fully distributed to miners” mechanism to a new model that burns the base fees and transfers only the tips to the miners. By burning the base fees of each block, the protocols add a deflationary pressure to the ETH currency.

Previously, before the EIP-1559 upgrade, a transaction fee was simply calculated by multiplying the amount of gas required for the transaction by a gas price parameter, which was provided by the user. The fee was entirely transferred to the miner that included the transaction to the block.

Moving to EIP-1559, there are three new parameters, which are central to transaction pricing, that must be fully understood:

baseFeePerGasbaseFeePerGasmaxPriorityFeePerGasmaxFeePerGasmaxPriorityFee

To send a new EIP-1559 transaction, the max fee and priority fee must be specified. This is called a Type 2 transaction. Ethereum is backward-compatible for sending legacy transactions (Type 0) by specifying the gas price parameter.

With EIP-1559 under normal network congestion levels, users have an improved UX because they can be much more certain that their transaction is included in one of the next blocks without overpaying in terms of gas costs.

Let’s take the following example: a user wants to include their transaction on one of the next blocks. With the old mechanism, they had to check the market price, for example, 100 gwei (1 gwei = 0.000000001 ether), and then choose a gas price exceeding the current price. However, there is no guarantee that their transaction will eventually be added to one of the next blocks if the market price rises.

A user could choose 1000 gwei to be safe that their transaction will be added to the next block, but then they will heavily overpay for that transaction.

With EIP-1559, this is different due to the new fee mechanism and flexible block space. If the user chooses a max fee of 1000 gwei and a reasonably priced priority fee (for example, 3 gwei), they can be much more certain that the transaction will be included in one of the next blocks. Furthermore, they won’t overpay because the current base fee and priority fee are dynamically adjusted by the network, but not the manually set max fee.

However, if the network is congested (such as due to an NFT sale) and the blocks are 200% utilized, the fee market reverts to a first price auction mechanism based on the provided priority fee history to the EIP-1559 upgrade.

Solution overview

The following diagram illustrates the architecture of our solution:

The scope of the provided solution in the AWS CDK repository is limited to the area within the dotted red line.

Prerequisites

To follow along with this post, we recommend reading the Prerequisites and Deploy the solution with the AWS CDK sections of Part 1.

To just make the source code available to your local system, you have to clone the repository from GitHub:

Sign an Ethereum EIP-1559 transaction with a KMS key

Following the steps of this post, you can create and sign an Ethereum transaction without further requirements. To publish a transaction to the Ethereum network, you need to hold an account that is sufficiently funded. To fund an account on an Ethereum testnet like Rinkeby, you can use the Rinkeby faucet.

To determine the AWS KMS-based Ethereum address, you first have to run a Lambda function that returns the public Ethereum address of the AWS KMS-based account.

The random suffix attached to the Lambda function is related to how the AWS CDK names and identifies the resources.

{"operation": "status"}
eth_checksum_address
  1. To create and sign an Ethereum transaction with the given AWS KMS-based address, run a Lambda function using the following JSON snippet:

The preceding snippet has the following values:

amountdst_addressnoncetypechainidmax_priority_fee_per_gasmax_fee_per_gasbase_fee_per_gasmax_priority_fee_per_gas
nonceeth_get_TransactionCountnonce

Congratulations! You have created your first KMS key-backed Ethereum EIP-1559 transaction.

For instructions on sending off the transaction via a Managed Blockchain Ethereum node, see Deploying an Ethereum Node on Amazon Managed Blockchain. The newly created Lambda function from the referenced post authenticates with your dedicated Managed Blockchain Ethereum node using Signature Version 4 authentication. You have to provide the hex-encoded Ethereum transaction as an input parameter to the Ethereum client Lambda function, as shown in the following Node.JS example:

tx_id

For details about the AWS CDK, refer to the section What is happening under the hood? in Part 1.

This particular post mainly focuses on how EIP-1559 transactions are different from legacy transactions explained in Part 1 and Part 2.

Protocol specification

On a protocol level, EIP-1559 introduces a new transaction type that also requires changes to the signature schema described in Part 2.

noncegaspricestartgastovaluedata

This mechanism is still valid after the introduction of the EIP-1559 standard via the Ethereum London update that happened on August 5, 2021.

22

The main differentiator in terms of the transaction body between the legacy transaction explained in Part 2 and the new EIP-1559 format is that now nine fields need to be included, instead of the previous six fields.

The newly required fields are:

chainidmax_prioirty_fee_per_gasmax_fee_per_gasaccess_list

The change of the transaction format is also reflected in a change of the transaction signature.

signature_y_paritysignature_rsignature_s
vsignature_y_parity
signature_y_parity{0,1}yr
chainidchainid
chainidchainidchainid
chainid

Replaying the same transaction on the same network is impossible because the nonce needs to reflect the current transaction count of an Ethereum account. If the transaction has been accepted in the destination network already, the nonce must be incremented for subsequent transactions, otherwise they’re rejected by the network.

chainid

JSON RPC considerations

max_prioirty_fee_per_gasmax_fee_per_gas
eth_feeHistorymax_fee_per_gasmax_fee_per_gasmax_priority_fee_per_gasbase_fee
max_priority_fee_per_gas

Lambda function (Ethereum EIP-1559 transaction generation)

eth_client_eip1559aws-kms-ethereum-accounts/_lambda/functions/eth_client_eip1559
lambda_function.pylambda_handler(event, context)
statussign
signevent

This post puts the focus on the differences between legacy transactions described in Part 1 and Part 2 and the EIP-1559 type transactions also called typed transactions. Fundamentals like ASN.1 schema decoding and other aspects have already been covered in Part 2.

get_tx_params()typemaxFeePerGasmaxPriorityFeePerGasschainId
typeeth_accountserializable_unsigned_transaction_from_dict2
eth_accountTypedTransaction
typedTransactionhash()
access_listnull
tx_hash
signature_y_parityrsget_recovery_idtx_hasheth_checksum_addrchainid
v
rsparity_y
vchainid{0,1} + CHAIN_ID * 2 + 35{0,1}y
Account.recoverHash()recoverHash()eth_checksum_addrvsignature_y_parity
chainid
{0,1} + CHAIN_ID * 2 + 35v_lowerv_range
Account.recoverHash()
y_parityv_lower41 = 0 + 3 * 2 + 35vy_parity
y_parityencode_transactions()eth_account

Lastly, the returned signed transaction must be converted into a hex string:

This has the benefit that it’s portable and protected against encoding issues. Furthermore, it allows the calculation of the Ethereum transaction ID or transaction hash.

As shown in the following code, the signed transaction and the associated hash value are being returned as the last step:

As mentioned earlier, we can use the transaction hash value, for example on Etherscan, to query the status of an Ethereum transaction after the signed transaction has been submitted to a network.

Clean up

To avoid incurring future charges, delete the resources using the AWS CDK with the following command:

You can also delete the stacks deployed by the AWS CDK via the AWS CloudFormation console.

Conclusion

This series of posts discussed managing Ethereum key material using a KMS key and Lambda.

In Part 1, we talked about how to set up the required services for an AWS-based Ethereum transaction and signature creation, namely AWS KMS and Lambda, using the AWS CDK. The post also pointed out how you can send signed transactions to the Ethereum Rinkeby test network using a Managed Blockchain Ethereum mode.

In Part 2, we explained the inner workings of the Ethereum signature process and the related elliptic curve cryptography, and demonstrated in detail how to create Ethereum legacy transactions and sign them using Lambda functions.

In this post, we introduced EIP-1559 and explained in detail how the new fee mechanism works and how to set the required parameters. We introduced the notion of typed transactions, and provided an in-depth comparison of legacy transactions, EIP-155, and the EIP-1559 transaction type. We also used the Lambda-based mechanism to create valid AWS KMS-based EIP-1559 Ethereum transactions.

Now go, deploy, sign your first EIP-1559 transaction and send it off via an Amazon Managed Blockchain Ethereum node!


About the Authors

David Dornseifer is a Blockchain Architect with the Amazon ProServe Blockchain team. He focuses on helping customers design, deploy and scale end-to-end Blockchain solutions.

Thomas von Bomhard is a Blockchain Architect on the AWS Professional Services team. He has been working with blockchain technology since 2017, and is excited to design and build end-to-end Ethereum blockchain solutions for our customers from various industries.