Skip to content

Commit

Permalink
EIP1559 (#31)
Browse files Browse the repository at this point in the history
* change transaction options, gasPremium to maxMinerBribePerGas

* update fields for eth api

* Update cost calculation for transaction

* Change gasPremium to maxMinerBribePerGas

* update baseFee calculation

* fix gasprice calculation for StateTransition

* fix fields for RPCTransaction

* fix CalcBaseFee

* fix transaction fields for test

* add additional func computeBaseFee

* fix baseFee values for TestCalcBaseFee

* Fix transaction cost calculation

* add infomation about eip version

* use camelCase-style for json tags

* remove eip info from "version"-command

* update VesionMeta

Co-authored-by: Ilnur Galiev <[email protected]>
  • Loading branch information
ramilexe and n0cte committed Dec 11, 2020
1 parent eaa6339 commit 5784a0e
Show file tree
Hide file tree
Showing 25 changed files with 399 additions and 392 deletions.
46 changes: 23 additions & 23 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,23 +557,23 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// If we have finalized EIP1559 and do not have a properly formed EIP1559 trx, sub in default values
eip1559 := b.config.IsEIP1559(block.Number())
eip1559Finalized := b.config.IsEIP1559Finalized(block.Number())
if eip1559Finalized && (call.GasPremium == nil || call.FeeCap == nil || call.GasPrice != nil) {
call.GasPremium = big.NewInt(1)
call.FeeCap = big.NewInt(10)
if eip1559Finalized && (call.MaxMinerBribePerGas == nil || call.FeeCapPerGas == nil || call.GasPrice != nil) {
call.MaxMinerBribePerGas = big.NewInt(1)
call.FeeCapPerGas = big.NewInt(10)
call.GasPrice = nil
}
// If we have not activated EIP1559 and do not have a properly formed legacy trx, sub in default values
if !eip1559 && (call.GasPremium != nil || call.FeeCap != nil || call.GasPrice == nil) {
call.GasPremium = nil
call.FeeCap = nil
if !eip1559 && (call.MaxMinerBribePerGas != nil || call.FeeCapPerGas != nil || call.GasPrice == nil) {
call.MaxMinerBribePerGas = nil
call.FeeCapPerGas = nil
call.GasPrice = big.NewInt(1)
}
// If we are in between activation and finalization
if eip1559 && !eip1559Finalized {
// and we have neither a properly formed legacy or EIP1559 transaction, sub in default legacy values
if (call.GasPremium == nil || call.FeeCap == nil && call.GasPrice == nil) || (call.GasPremium != nil || call.FeeCap != nil && call.GasPrice != nil) {
call.GasPremium = nil
call.FeeCap = nil
if (call.MaxMinerBribePerGas == nil || call.FeeCapPerGas == nil && call.GasPrice == nil) || (call.MaxMinerBribePerGas != nil || call.FeeCapPerGas != nil && call.GasPrice != nil) {
call.MaxMinerBribePerGas = nil
call.FeeCapPerGas = nil
call.GasPrice = big.NewInt(1)
}
}
Expand Down Expand Up @@ -614,16 +614,16 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
if eip1559 && b.pendingBlock.BaseFee() == nil {
return core.ErrNoBaseFee
}
if eip1559Finalized && (tx.GasPremium() == nil || tx.FeeCap() == nil || tx.GasPrice() != nil) {
if eip1559Finalized && (tx.MaxMinerBribe() == nil || tx.FeeCap() == nil || tx.GasPrice() != nil) {
return core.ErrTxNotEIP1559
}
if !eip1559 && (tx.GasPremium() != nil || tx.FeeCap() != nil || tx.GasPrice() == nil) {
if !eip1559 && (tx.MaxMinerBribe() != nil || tx.FeeCap() != nil || tx.GasPrice() == nil) {
return core.ErrTxIsEIP1559
}
if tx.GasPrice() != nil && (tx.GasPremium() != nil || tx.FeeCap() != nil) {
if tx.GasPrice() != nil && (tx.MaxMinerBribe() != nil || tx.FeeCap() != nil) {
return core.ErrTxSetsLegacyAndEIP1559Fields
}
if tx.GasPrice() == nil && (tx.GasPremium() == nil || tx.FeeCap() == nil) {
if tx.GasPrice() == nil && (tx.MaxMinerBribe() == nil || tx.FeeCap() == nil) {
return core.ErrMissingGasFields
}

Expand Down Expand Up @@ -775,16 +775,16 @@ type callMsg struct {
ethereum.CallMsg
}

func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) CheckNonce() bool { return false }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) GasPremium() *big.Int { return m.CallMsg.GasPremium }
func (m callMsg) FeeCap() *big.Int { return m.CallMsg.FeeCap }
func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) CheckNonce() bool { return false }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) MaxMinerBribe() *big.Int { return m.CallMsg.MaxMinerBribePerGas }
func (m callMsg) FeeCap() *big.Int { return m.CallMsg.FeeCapPerGas }

// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
Expand Down
26 changes: 13 additions & 13 deletions accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ type TransactOpts struct {
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)

// If GasPrice, GasPremium, and FeeCap are all nil then we defer to the gas price oracle
GasPrice *big.Int // Gas price to use for the transaction execution
GasPremium *big.Int // Gas premium (tip) to use for EIP1559 transaction execution (
FeeCap *big.Int // Fee cap to use for EIP1559 transaction execution
GasPrice *big.Int // Gas price to use for the transaction execution
MaxMinerBribePerGas *big.Int // Gas premium (tip) to use for EIP1559 transaction execution (
FeeCapPerGas *big.Int // Fee cap to use for EIP1559 transaction execution

Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
Expand Down Expand Up @@ -227,7 +227,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
// Figure out the gas allowance and gas price values
gasPrice := opts.GasPrice
if gasPrice == nil && opts.FeeCap == nil && opts.GasPremium == nil {
if gasPrice == nil && opts.FeeCapPerGas == nil && opts.MaxMinerBribePerGas == nil {
gasPrice, err = c.transactor.SuggestGasPrice(ensureContext(opts.Context))
if err != nil {
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
Expand All @@ -245,13 +245,13 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
// If the contract surely has code (or code is not needed), estimate the transaction
msg := ethereum.CallMsg{
From: opts.From,
To: contract,
GasPrice: gasPrice,
Value: value,
Data: input,
GasPremium: opts.GasPremium,
FeeCap: opts.FeeCap,
From: opts.From,
To: contract,
GasPrice: gasPrice,
Value: value,
Data: input,
MaxMinerBribePerGas: opts.MaxMinerBribePerGas,
FeeCapPerGas: opts.FeeCapPerGas,
}
gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg)
if err != nil {
Expand All @@ -261,9 +261,9 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
// Create the transaction, sign it and schedule it for execution
var rawTx *types.Transaction
if contract == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input, opts.GasPremium, opts.FeeCap)
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input, opts.MaxMinerBribePerGas, opts.FeeCapPerGas)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input, opts.GasPremium, opts.FeeCap)
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input, opts.MaxMinerBribePerGas, opts.FeeCapPerGas)
}
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")
Expand Down
18 changes: 9 additions & 9 deletions accounts/external/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,15 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
to = &t
}
args := &core.SendTxArgs{
Data: &data,
Nonce: hexutil.Uint64(tx.Nonce()),
Value: hexutil.Big(*tx.Value()),
Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
GasPremium: (*hexutil.Big)(tx.GasPremium()),
FeeCap: (*hexutil.Big)(tx.FeeCap()),
To: to,
From: common.NewMixedcaseAddress(account.Address),
Data: &data,
Nonce: hexutil.Uint64(tx.Nonce()),
Value: hexutil.Big(*tx.Value()),
Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
MaxMinerBribePerGas: (*hexutil.Big)(tx.MaxMinerBribe()),
FeeCapPerGas: (*hexutil.Big)(tx.FeeCap()),
To: to,
From: common.NewMixedcaseAddress(account.Address),
}
var res signTransactionResult
if err := api.client.Call(&res, "account_signTransaction", args); err != nil {
Expand Down
72 changes: 37 additions & 35 deletions consensus/misc/basefee.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package misc

import (
"errors"

"math/big"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -59,6 +60,37 @@ func VerifyEIP1559BaseFee(config *params.ChainConfig, header, parent *types.Head
return nil
}

func computeBaseFee(pBaseFee *big.Int, pGasUsed, pGasTarget, denominator uint64) *big.Int {
var baseFee *big.Int
if pGasUsed == pGasTarget {
baseFee = new(big.Int).Set(pBaseFee)
} else if pGasUsed > pGasTarget {
gasDelta := big.NewInt(int64(pGasUsed) - int64(pGasTarget))
feeDelta := math.BigMax(
new(big.Int).Div(
new(big.Int).Mul(pBaseFee, gasDelta),
new(big.Int).Mul(
new(big.Int).SetUint64(pGasTarget),
new(big.Int).SetUint64(denominator),
),
),
big.NewInt(1),
)
baseFee = new(big.Int).Add(pBaseFee, feeDelta)
} else {
gasDelta := big.NewInt(int64(pGasTarget) - int64(pGasUsed))
feeDelta := new(big.Int).Div(
new(big.Int).Mul(pBaseFee, gasDelta),
new(big.Int).Mul(
new(big.Int).SetUint64(pGasTarget),
new(big.Int).SetUint64(denominator),
),
)
baseFee = new(big.Int).Sub(pBaseFee, feeDelta)
}
return baseFee
}

// CalcBaseFee returns the baseFee for the current block provided the parent header and config parameters
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
height := new(big.Int).Add(parent.Number, common.Big1)
Expand All @@ -73,42 +105,12 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
return new(big.Int).SetUint64(config.EIP1559.InitialBaseFee)
}

parentBaseFee := parent.BaseFee
parentBlockGasUsed := new(big.Int).SetUint64(parent.GasUsed)
targetGasUsed := new(big.Int).SetUint64(parent.GasLimit)
baseFeeMaxChangeDenominator := new(big.Int).SetUint64(config.EIP1559.EIP1559BaseFeeMaxChangeDenominator)

cmp := parentBlockGasUsed.Cmp(targetGasUsed)

if cmp == 0 {
return targetGasUsed
}

if cmp > 0 {
gasDelta := new(big.Int).Sub(parentBlockGasUsed, targetGasUsed)
feeDelta := math.BigMax(
new(big.Int).Div(
new(big.Int).Div(
new(big.Int).Mul(parentBaseFee, gasDelta),
targetGasUsed,
),
baseFeeMaxChangeDenominator,
),
common.Big1,
)
return new(big.Int).Add(parentBaseFee, feeDelta)
}

gasDelta := new(big.Int).Sub(targetGasUsed, parentBlockGasUsed)
feeDelta := new(big.Int).Div(
new(big.Int).Div(
new(big.Int).Mul(parentBaseFee, gasDelta),
targetGasUsed,
),
baseFeeMaxChangeDenominator,
return computeBaseFee(
parent.BaseFee,
parent.GasUsed,
parent.GasLimit,
config.EIP1559.EIP1559BaseFeeMaxChangeDenominator,
)

return new(big.Int).Sub(parentBaseFee, feeDelta)
}

// CalcEIP1559GasTarget returns the EIP1559GasTarget at the current height and header.GasLimit
Expand Down
32 changes: 13 additions & 19 deletions consensus/misc/basefee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1000000000),
1000000,
10000000,
big.NewInt(1125000000),
big.NewInt(2125000000),
},
{
params.EIP1559ChainConfig,
Expand All @@ -165,7 +165,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1000000000),
500000,
10000000,
big.NewInt(1125000000),
big.NewInt(3375000000),
},
{
params.EIP1559ChainConfig,
Expand All @@ -175,7 +175,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1000000000),
1000000,
10000000,
big.NewInt(1125000000),
big.NewInt(2125000000),
},
{
params.EIP1559ChainConfig,
Expand Down Expand Up @@ -217,15 +217,15 @@ func TestCalcBaseFee(t *testing.T) {
10000000,
big.NewInt(1013888888),
},
{
{ // 10
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
10000000,
10000000,
big.NewInt(999999999), // baseFee diff is -1 when usage == target
big.NewInt(1000000000), // baseFee diff is -1 when usage == target
},
{
params.EIP1559ChainConfig,
Expand All @@ -235,7 +235,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1000000000),
11000000,
10000000,
big.NewInt(988636363),
big.NewInt(988636364),
},
{
params.EIP1559ChainConfig,
Expand All @@ -245,7 +245,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(900000000),
1000000,
10000000,
big.NewInt(1012500000),
big.NewInt(1912500000),
},
{
params.EIP1559ChainConfig,
Expand All @@ -255,7 +255,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1100000000),
1000000,
10000000,
big.NewInt(1237500000),
big.NewInt(2337500000),
},
{
params.EIP1559ChainConfig,
Expand All @@ -265,7 +265,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1200000000),
1000000,
10000000,
big.NewInt(1350000000),
big.NewInt(2550000000),
},
{
params.EIP1559ChainConfig,
Expand Down Expand Up @@ -328,7 +328,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(0),
1000000000000000,
1,
big.NewInt(1),
big.NewInt(0),
},
// parent gas usage == parent gas limit
// parent baseFee == 0
Expand All @@ -355,11 +355,8 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1),
1,
1000000000000000,
big.NewInt(2),
big.NewInt(125000000000000),
},
// parent gas usage <<<< parent gas limit
// parent baseFee == 1
// as expected, decrement by 1
{
params.EIP1559ChainConfig,
big.NewInt(1000),
Expand All @@ -368,11 +365,8 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1),
1000000000000000,
1,
big.NewInt(0),
big.NewInt(1),
},
// parent gas usage == parent gas limit
// parent baseFee == 1
// as expected, decrement by 1 when gas usage equals the gas target
{
params.EIP1559ChainConfig,
big.NewInt(1000),
Expand All @@ -381,7 +375,7 @@ func TestCalcBaseFee(t *testing.T) {
big.NewInt(1),
1,
1,
big.NewInt(0),
big.NewInt(1),
},
}
for i, test := range testConditions {
Expand Down
Loading

0 comments on commit 5784a0e

Please sign in to comment.