Cover photo

EIP-1559 & Gas Estimation

EIP-155

  • Replay Attack Protection

  • ChainID

https://chainlist.org/

EIP-1559 (London)

https://eips.ethereum.org/EIPS/eip-1559

Why EIP-1559?

  • Background:

    • ETH token-nomic (Inflation, Deflation)

    • Miner income

      • Block Reward (also, Uncle Block Reward)

      • Transaction Fee (Gas) -- reached nearly half of Block Reward - Security Issue

      • MEV

  • Issues

    • Gas War

    • Congestion

    • Security threat by Miners

Mainly About

  • Base Fee -- Burn

  • Priority Fee -- Miner

  • Max Fee -- Remaining Part will be refund to sender

Transactions on explorer

Legacy TX:

https://etherscan.io/tx/0x177767d9398486c932d8b1e289e55a8e3b843a381b7470920a4339de775f4c0f

EIP-1559 TX:

https://etherscan.io/tx/0x84c1a231c787cd3b4f031cfeb6a1d66bfb0a6e226e438e3accfda7be49e4cd6b

Remaining Issues

  • Gas War

  • NO Gas CELING

How to set up gas provider for EIP-1559?

Sample Code with Web3j:

// Get baseFee from last block
BigInteger baseFeePerGas = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false).send().getBlock().getBaseFeePerGas();
BigInteger maxPriorityFeePerGas = web3j.ethMaxPriorityFeePerGas().send().getMaxPriorityFeePerGas();
BigInteger maxFeePerGas = baseFeePerGas.add(maxPriorityFeePerGas);

Gas Estimation

What and Why?

Before the execution, would like to how much gas the transaction need to get successfully executed.

For better gas preparation;

For more reasonable fee structure;

For avoid most TX execution failures;

etc.

How?

Sample Code with Web3j:

private static ContractEIP1559GasProvider buildGasProviderForApprove(Web3j web3j, String fromAddress,
                                  String scAddress, String spender, BigInteger amountInWei) throws IOException {
    long chainId = web3j.ethChainId().send().getChainId().longValue();

    BigInteger baseFeePerGas = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false).send().getBlock().getBaseFeePerGas();
    BigInteger maxPriorityFeePerGas = web3j.ethMaxPriorityFeePerGas().send().getMaxPriorityFeePerGas();

    BigInteger maxFeePerGas = baseFeePerGas.add(maxPriorityFeePerGas);

    BigInteger gasLimit = estimateApproveGasLimit(web3j, fromAddress, scAddress, spender, amountInWei, maxFeePerGas, maxPriorityFeePerGas);
    return new StaticEIP1559GasProvider(chainId, maxFeePerGas, maxPriorityFeePerGas, gasLimit);
}

private static BigInteger estimateApproveGasLimit(Web3j web3j, String fromAddress, String scAddress, String spender, BigInteger amountInWei,
                                                  BigInteger maxFeePerGas, BigInteger maxPriorityFeePerGas) throws IOException {
    Function function = new org.web3j.abi.datatypes.Function(
            "approve",
            Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(160, spender),
                    new org.web3j.abi.datatypes.generated.Uint256(amountInWei)),
            Collections.<TypeReference<?>>emptyList());

    EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(fromAddress, DefaultBlockParameterName.PENDING).send();
    BigInteger nonce = ethGetTransactionCount.getTransactionCount();
    long chainId = web3j.ethChainId().send().getChainId().longValue();

    Transaction transaction = new Transaction(fromAddress, nonce, null, BigInteger.valueOf(4300000),
            scAddress, BigInteger.ZERO, FunctionEncoder.encode(function), chainId, maxPriorityFeePerGas, maxFeePerGas);
    BigInteger gasLimit = web3j.ethEstimateGas(transaction).send().getAmountUsed();

    return gasLimit;
}