Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas price market change: Escalator Algorithm (alternative to 1559) #2593

Merged
merged 18 commits into from
Sep 11, 2020
Merged
140 changes: 140 additions & 0 deletions EIPS/eip-x.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
eip: tbd
danfinlay marked this conversation as resolved.
Show resolved Hide resolved
title: Escalator fee market change for ETH 1.0 chain
author: Dan Finlay <dan@danfinlay.com>
discussions-to: https://ethresear.ch/t/another-simple-gas-fee-model-the-escalator-algorithm-from-the-agoric-papers/6399
status: Draft
type: Standards Track
category: Core
created: 2020-03-13
---

<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->

danfinlay marked this conversation as resolved.
Show resolved Hide resolved
## Simple Summary
<!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP.-->
danfinlay marked this conversation as resolved.
Show resolved Hide resolved
The current "first price auction" fee model in Ethereum is inefficient and needlessly costly to users. This EIP proposes a way to replace this with a mechanism that allows dynamically priced transaction fees and efficient transaction price discovery.

## Abstract

Based on [The Agoric Papers](https://agoric.com/papers/incentive-engineering-for-computational-resource-management/full-text/).

Each transaction would have the option of providing parameters that specify an "escalating" bid, creating a time-based auction for validators to include that transaction.

This creates highly efficient price discovery, where the price will always immediately fall to the highest bid price, which is not necessarily that user's highest price they would pay.

![escalator algorithm price chart](https://ethresear.ch/uploads/default/original/2X/0/042795efa4c2680d644bc66386cd2984a70293f8.gif)

## Motivation
<!--The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright.-->
danfinlay marked this conversation as resolved.
Show resolved Hide resolved
Ethereum currently prices transaction fees using a simple first-price auction, which leads to well documented inefficiencies (some of which are documented in [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)) when users are trying to estimate what price will get a transaction included in a block, especially during times of price volatility and full blocks.

EIP 1559 is currently being championed as an improvement for the Ethereum protocol, and while I agree that the gas market is very inefficient, since a change like this will affect all client and wallet implementations, the Ethereum community should make sure to make a selection based on solid reasoning and justifications, which I believe 1559 is currently lacking.

To facilitate a more productive and concrete discussion about the gas fee market, I felt it was important to present an alternative that is clearly superior to the status quo, so that any claimed properties of EIP-1559 can be compared to a plausible alternative improvement.

I suggest the three gas payment algorithms be compared under all combinations of these conditions:

- Blocks that are regularly half full, Blocks that are regularly less than half full, and blocks that repeatedly full in a surprising ("black swan") series.
- Users that are willing to wait for a price that may be below the market rate, vs users who value inclusion urgently and are willing to pay above market rate.

We should then ask:
- Is the user willing to pay the most in a given scenario also likely to have their transaction processed in a time period they find acceptable?
- Are users who want a good price likely to get included in a reasonable period of time? (Ideally within one block)

I believe that under this analysis we will find that the escalator algorithm outperforms EIP-1559 in both normal and volatile conditions, for both high-stakes transactions and more casual users looking for a good price.

While I think a deeper simulation/analysis should be completed, I will share my expected results under these conditions.

### User Strategies Under Various Conditions and Algorithms

First I will suggest a likely optimal strategy for different players under the conditions of the different algorithms being considered.

| Gas Strategy | Current Single-Price | EIP 1559 | Escalator |
|---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Blocks regularly half full, user wants urgent inclusion. | User bids within the range of prices that have been recently accepted, likely over-pays slightly. | User bids one price tier over the current rate, and is likely included. | User bids a range from the low end of recently included to the high end, and is likely included at the lowest rate possible. |
| Blocks regularly half full, user willing to wait for a good price. | User bids below or near the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User bids under or at the current price tier, and may wait for the price to fall. If waiting too long, user may need to re-submit with a higher price. | User bids as low as they'd like, but set an upper bound on how long they're willing to wait before increasing price. |
| Blocks regularly full, user wants urgent inclusion. | User bids over the price of all recently accepted transactions, almost definitely over-paying significantly. | User bids over the current price tier, and needs to increase their `tip` parameter to be competitive on the next block, recreating the single-price auction price problem. | User bids over a price that has been accepted consistently, with an escalating price in case that price is not high enough. |
| Blocks regularly full, user willing to wait for a good price. | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User bids under or at the current price tier, and may wait for the price to fall. If waiting too long, user may need to re-submit with a higher price. | User bids as low as they'd like, but set an upper bound on how long they're willing to wait before increasing price. |
| Blocks regularly under-full, user wants urgent inclusion. | User bids within or over the range of prices that have been recently accepted, likely over-pays slightly, and is likely included in the next block. | User bids at or over the current price tier, and is likely included in the next block. | User submits bid starting within recently accepted prices, is likely accepted in the next block. |
| Blocks regularly under-full, user willing to wait for a good price. | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User bids at or under the current price tier, and is likely included in the next block. If bidding under and waiting too long, user may need to re-submit with a higher price. | User bids as low as they'd like, but set an upper bound on how long they're willing to wait before increasing price, is likely included in the next few blocks at the lowest possible price. |

### User Results Under Various Conditions and Algorithms

Now I will consider the ultimate results of the strategies listed above. Are users happy under these conditions? Did we save users money? Were users who wanted urgent inclusion able to secure it?

| Gas Strategy | Current Single-Price | EIP 1559 | Escalator |
|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| Blocks regularly half full, user wants urgent inclusion. | User pays an expected amount, and gets transaction mined reliably. | User pays an expected amount, and gets transaction mined reliably. | User pays an expected amount, and gets transaction mined reliably. |
| Blocks regularly half full, user willing to wait for a good price. | User can wait for a better price, but may need to resubmit re-signed transactions. | User can wait for a better price, but may need to resubmit re-signed transactions. | User can discover the lowest price within their time preference with a single signature. |
| Blocks regularly full, user wants urgent inclusion. | User over-pays, but reliably gets transaction included. | Due to `tip` parameter "breaking tie" within a block, user over-pays for reliable inclusion. | User is able to balance the amount of overpayment they risk with the urgency they require. |
| Blocks regularly full, user willing to wait for a good price. | User chooses their price, and waits for it, or manually re-submits. | User chooses their price, and waits for it, or manually re-submits. | User chooses their lowest price, but also their highest price and maximum wait time, so no resubmission is needed. |
| Blocks regularly under-full, user wants urgent inclusion. | User over-pays, but reliably gets transaction included. | User bids at or over current price tier, gets transaction mined reliably. | User pays an expected amount, and gets transaction mined reliably. |
| Blocks regularly under-full, user willing to wait for a good price. | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User chooses their price, and waits for it, or manually re-submits. | User chooses their lowest price, but also their highest price and maximum wait time, so no resubmission is needed. |

In all cases, the escalator algorithm as I have described is able to perform optimally.

The current gas auction model works well under half-full and less conditions, but for users with urgent needs, has the downside of overpayment. For users seeking a low price, the current model has the downside of requiring re-submission, but has the benefit of always giving users a path towards reliable block inclusion.

EIP-1559 also performs well under normal conditions, but under conditions where blocks are regularly full, the price discovery mechanism breaks, and miners will fall back to the `TIP` parameter to choose the transactions to include, meaning that under network congestion, EIP-1559 forces users to _either_ choose efficient prices or certainty of next-block inclusion.

EIP-1559 also has all the re-submission issues of the current model in situations where a user would like to pay under the current market rate, but has certain time constraints limiting their patience. The Escalator algorithm is the only strategy listed here that allows users to discover the lowest possible price given the network conditions and their time constraints.

## Specification
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).-->

danfinlay marked this conversation as resolved.
Show resolved Hide resolved
**Client-Wide Parameters**
* `INITIAL_FORK_BLKNUM`: TBD

**Transaction Parameters**
The transaction `gasPrice` parameter is now optional, and if excluded can be replaced by these parameters instead:

* `START_PRICE`: The lowest price that the user would like to pay for the transaction.
* `START_BLOCK`: The first block that this transaction is valid at.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the START_BLOCK actually defined? If a transaction could have been valid at block 1000, but it has been created at block 2000, what is the START_BLOCK in such case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, what happens if START_BLOCK is in the future? Can this EIP also solve the problem of delayed transactions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question was basically a hint that START_BLOCK probably cannot be suitably defined (so that it can be efficiently calculated from consensus values, and not just from subjective tx pool timestamps), and this could be the main thing that makes this EIP hard or impossible to implement

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean suitably defined? The user or user's wallet specifies the START_BLOCK and MAX_BLOCK in the transaction, just like with gas price and gas limit. If the miner is working on a block with number BLOCK_NUMBER, the block is valid iff all transactions within the block have START_BLOCK <= BLOCK_NUMBER and MAX_BLOCK >= BLOCK_NUMBER

It's very easy for a wallet to set this parameter. Just choose the next block for START_BLOCK and the MAX_BLOCK to whatever delay the user is willing to tolerate divided by the 15 seconds average block times plus the start block.

This constraint can be cheaply validated by any node, and adds some compute time to ordering transactions into a block (must determine the gas price for each transaction for the given block, and whether it can be included) but also has the benefit that transactions can be dropped from the mempool as soon as the block number exceeds MAX_BLOCK by some threshold, and potentially if they are sent with a START_BLOCK too far in the future

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I misunderstood, now I see that START_BLOCK is suggested to be a new transaction parameter. Thank you

* `MAX_PRICE`: The maximum price the sender would be willing to pay to have this transaction processed.
* `MAX_BLOCK`: The last block that the user is willing to wait for the transaction to be processed in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of the transaction getting dropped when max-block is reached. In most cases I would want to escalate up to target price and then sit at that target price until mined or cancelled. I can also imagine situations where I want to "mine by this block or give up", so I can appreciate the desire but I don't think it is the common case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for highlighting this distinction. I think I agree with you as the default case, especially since it resembles current behavior more, but I think there is a use case (for a future EIP, perhaps a new tx type) to allow TXs that become invalid over time or after some conditions. Making this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider changing this to START_TIME and MAX_TIME instead. Miners can only fudge the block timestamp a little, and it is very costly for them to fudge the timestamp into the future. Timestamps are much easier for humans, and also much more reliable (block times range from 1 second to 100 seconds) so using block numbers can result in very unexpected (for a human) wait times.

Also, by using timestamps here we will incentivize miners to more accurately set block timestamps than they do now. Right now, many miners set timestamps far (30+ seconds) in the past because there is a very marginal advantage for them to have their clocks be off by a bit. By having this be timestamp based, miners are strongly encouraged to set the timestamp as far forward as they can without risking significant profits. It turns out, that is just about now because they start taking on huge risk by setting block.timestamp to the future. This means that we can kill two birds with one stone with this PR by having gas price (or gas premium) be a function of time instead of block number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting point, and I have no objection, so I've made this change. I hope this doesn't greatly complicate any analyses that are currently in progress.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

START_BLOCK/MAX_BLOCK is inconsistent, prefer MIN_BLOCK/MAX_BLOCK or START_BLOCK/END_BLOCK


**Proposal**

For all blocks where `block.number >= INITIAL_FORK_BLKNUM`:

When processing a transaction with the new pricing parameters, miners now receive a fee based off of the following linear function, where `BLOCK` is the current block number:

* IF `BLOCK > MAX_BLOCK` then `TX_FEE = MAX_PRICE`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ideal behavior imo is that the transaction cannot be included after the MAX_BLOCK

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this wording conflicts with the wording above on MAX_BLOCK. I disagree with @moodysalem here and think that the ideal behavior (if we have to choose between two options) is to have it sit at MAX_PRICE forever once MAX_BLOCK is reached.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see people complain about transactions pending for days, blocking new things they want to do, in basically every dapp's support chat. Cancelling transactions via resubmitting with different gas price is a horrible experience, and has non-deterministic results. If you really want to wait up to 3 days for a transaction, set the MAX_BLOCK to last 3 days.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the fee algorithm is a function of MAX_BLOCK, START_BLOCK, so if you set MAX_BLOCK to 3 days in the future, your fee increase rate is really slow. I would not be opposed to adding yet-another-variable for TERMINATION_BLOCK, so you can escalate up to a target fee over say 5 minutes, but then sit in the pending queue for up to 24 hours at that fee.

In other words, I agree that there is a problem with never-expiring transactions. I just disagree that MAX_BLOCK in this specification is the right place to fix that. In fact, one could create a totally separate EIP that just adds in a NOT_AFTER field to transactions.

* `TX_FEE = START_PRICE + ((MAX_PRICE - START_PRICE) / (MAX_BLOCK - START_BLOCK) * (BLOCK - START_BLOCK))`

As a JavaScript function:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest this could be a smart contract that implements this function in the future, but by default linear?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could be, I looked at some other EIPs and it seemed like pseudocode is fairly common for layer-1 proposals, but I'd gladly add specificity anywhere it's lacking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, I mean that the EIP could specify that a linear 'escalator' algorithm is just one of a number of gas price functions, which could be implemented as smart contracts and then specified by the user in the transaction as an address, gasPriceContractAddress. E.g. the specified contract could produce gas prices as a step function, or decreasing gas prices to encourage immediate inclusion. This may be way out of scope for this EIP though, but just worth mentioning as a hint towards the extensibility of this feature

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to prevent DoS attacks against the network, nodes need to be able to very quickly check to see if the caller can afford to submit the transaction, before executing arbitrary user-provided code. This ensures that someone can't waste node resources by submitting transactions to the network that are invalid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the DoS consideration is fair, but there is an obvious solution: limit how much gas the computation requires and make it pure. You still have to look up the code, but that can be easily memoized.

```javascript
function txFee (startBlock, startPrice, maxBlock, maxPrice, blockNumber) {

if (blockNumber >= maxBlock) return maxPrice

const priceRange = maxPrice - startPrice
const blockRange = maxBlock - startBlock
const slope = priceRange / blockRange

return startPrice + (slope * (blockNumber - startBlock))
}
```

## Backwards Compatibility

Since a current `gasPrice` transaction is effectively a flat-escalated transaction bid, it is entirely compatible with this model, and so there is no concrete requirement to deprecate current transaction processing logic, allowing cold wallets and hardware wallets to continue working for the forseeable future.

## Test Cases
<!--Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.-->
danfinlay marked this conversation as resolved.
Show resolved Hide resolved

## Implementation
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.-->
danfinlay marked this conversation as resolved.
Show resolved Hide resolved

## Security Considerations
<!--All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the "Security Considerations" section will be rejected. An EIP cannot proceed to status "Final" without a Security Considerations discussion deemed sufficient by the reviewers.-->
danfinlay marked this conversation as resolved.
Show resolved Hide resolved
The security considerations for this EIP are:
- None currently known.

## Resources
* [Original Magicians thread](https://ethresear.ch/t/another-simple-gas-fee-model-the-escalator-algorithm-from-the-agoric-papers/6399)

danfinlay marked this conversation as resolved.
Show resolved Hide resolved
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

danfinlay marked this conversation as resolved.
Show resolved Hide resolved