Skip to content

Commit aa72756

Browse files
committed
graphql: add EIP-1559 and celo gas handling
The GraphQL-Endpoint did not properly handle post-EIP1559 gas fees. To get the correct results based on the respective baseFee, we have to take a look at the used feeCurrency. To get at least some test coverage for this, I added one EIP-1559 transaction to the test data. This is still far from a thorough coverage of all relevant cases (different feeCurrency, the base fee is 0 in the test, so bugs for proper values might be hidden).
1 parent fcd4e09 commit aa72756

File tree

2 files changed

+75
-23
lines changed

2 files changed

+75
-23
lines changed

graphql/graphql.go

+27-22
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ func (t *Transaction) GasPrice(ctx context.Context) (hexutil.Big, error) {
228228
switch tx.Type() {
229229
case types.AccessListTxType:
230230
return hexutil.Big(*tx.GasPrice()), nil
231-
case types.DynamicFeeTxType:
231+
case types.DynamicFeeTxType, types.CeloDynamicFeeTxType:
232232
if t.block != nil {
233-
if baseFee, _ := t.block.BaseFeePerGas(ctx); baseFee != nil {
233+
if baseFee, _ := t.block.BaseFeePerGasForCurrency(ctx, tx.FeeCurrency()); baseFee != nil {
234234
// price = min(tip, gasFeeCap - baseFee) + baseFee
235235
return (hexutil.Big)(*math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee.ToInt()), tx.GasFeeCap())), nil
236236
}
@@ -246,16 +246,16 @@ func (t *Transaction) EffectiveGasPrice(ctx context.Context) (*hexutil.Big, erro
246246
if err != nil || tx == nil {
247247
return nil, err
248248
}
249-
header, err := t.block.resolveHeader(ctx)
250-
if err != nil || header == nil {
251-
return nil, err
249+
switch tx.Type() {
250+
case types.DynamicFeeTxType, types.CeloDynamicFeeTxType:
251+
if t.block != nil {
252+
if baseFee, _ := t.block.BaseFeePerGasForCurrency(ctx, tx.FeeCurrency()); baseFee != nil {
253+
// price = min(tip, gasFeeCap - baseFee) + baseFee
254+
return (*hexutil.Big)(math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee.ToInt()), tx.GasFeeCap())), nil
255+
}
256+
}
252257
}
253-
return (*hexutil.Big)(tx.GasPrice()), nil
254-
// TODO: Substitute GPM
255-
// if header.BaseFee == nil {
256-
// return (*hexutil.Big)(tx.GasPrice()), nil
257-
// }
258-
// return (*hexutil.Big)(math.BigMin(new(big.Int).Add(tx.GasTipCap(), header.BaseFee), tx.GasFeeCap())), nil
258+
return nil, nil
259259
}
260260

261261
func (t *Transaction) MaxFeePerGas(ctx context.Context) (*hexutil.Big, error) {
@@ -579,18 +579,23 @@ func (b *Block) GasUsed(ctx context.Context) (Long, error) {
579579
return Long(header.GasUsed), nil
580580
}
581581

582-
// TODO: Enable GasLimit graphQL interface
583-
584582
func (b *Block) BaseFeePerGas(ctx context.Context) (*hexutil.Big, error) {
585-
// header, err := b.resolveHeader(ctx)
586-
// if err != nil {
587-
// return nil, err
588-
// }
589-
// if header.BaseFee == nil {
590-
// return nil, nil
591-
// }
592-
// return (*hexutil.Big)(header.BaseFee), nil
593-
return nil, nil
583+
// To have an external API as compatible to geth as possible, we return the
584+
// base for celo gold, here. We can add a separate variable for the base
585+
// fees for each currency.
586+
return b.BaseFeePerGasForCurrency(ctx, nil)
587+
}
588+
589+
func (b *Block) BaseFeePerGasForCurrency(ctx context.Context, feeCurrency *common.Address) (*hexutil.Big, error) {
590+
header, err := b.resolveHeader(ctx)
591+
if err != nil {
592+
return nil, err
593+
}
594+
baseFee, err := b.backend.GasPriceMinimumForHeader(ctx, feeCurrency, header)
595+
if err != nil {
596+
return nil, err
597+
}
598+
return (*hexutil.Big)(baseFee), nil
594599
}
595600

596601
func (b *Block) Parent(ctx context.Context) (*Block, error) {

graphql/graphql_test.go

+48-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,43 @@ func TestGraphQLBlockSerialization(t *testing.T) {
161161
}
162162
}
163163

164+
// Tests that a graphQL request is successfully handled when graphql is enabled on the specified endpoint
165+
func TestGraphQLTransactionSerialization(t *testing.T) {
166+
stack := createNode(t, true, true)
167+
defer stack.Close()
168+
// start node
169+
if err := stack.Start(); err != nil {
170+
t.Fatalf("could not start node: %v", err)
171+
}
172+
173+
for i, tt := range []struct {
174+
body string
175+
want string
176+
code int
177+
}{
178+
{
179+
body: `{"query":"{ transaction(hash: \"0x22f565cfeb33d5e6f81c8923ef0633a49fef0848a089a6d8564b655d5605fb13\") { gas gasUsed gasPrice maxFeePerGas maxPriorityFeePerGas effectiveGasPrice index from { address } to { address } value inputData block { transactionCount baseFeePerGas } status type }}"}`,
180+
want: `{"data":{"transaction":{"gas":"0xc350","gasUsed":22604,"gasPrice":"0xa","maxFeePerGas":"0x7530","maxPriorityFeePerGas":"0xa","effectiveGasPrice":"0xa","index":2,"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x32","inputData":"0x","block":{"transactionCount":3,"baseFeePerGas":"0x0"},"status":1,"type":2}}}`,
181+
code: 200,
182+
},
183+
} {
184+
resp, err := http.Post(fmt.Sprintf("%s/graphql", stack.HTTPEndpoint()), "application/json", strings.NewReader(tt.body))
185+
if err != nil {
186+
t.Fatalf("could not post: %v", err)
187+
}
188+
bodyBytes, err := ioutil.ReadAll(resp.Body)
189+
if err != nil {
190+
t.Fatalf("could not read from response body: %v", err)
191+
}
192+
if have := string(bodyBytes); have != tt.want {
193+
t.Errorf("testcase %d %s,\nhave:\n%v\nwant:\n%v", i, tt.body, have, tt.want)
194+
}
195+
if tt.code != resp.StatusCode {
196+
t.Errorf("testcase %d %s,\nwrong statuscode, have: %v, want: %v", i, tt.body, resp.StatusCode, tt.code)
197+
}
198+
}
199+
}
200+
164201
func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
165202
stack := createNode(t, true, true)
166203
defer stack.Close()
@@ -176,7 +213,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
176213
}{
177214
{
178215
body: `{"query": "{block {number transactions { from { address } to { address } value hash type accessList { address storageKeys } index}}}"}`,
179-
want: `{"data":{"block":{"number":1,"transactions":[{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x64","hash":"0x46933b8a43e70320bb41910f015c4b2aded1caaba32b55b56054e4d1811d06d6","type":0,"accessList":[],"index":0},{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x32","hash":"0x03682ed7cc9cf9e9fa3bb6f58a62d6a350c09ec4d22b71b884503ae469e8640b","type":1,"accessList":[{"address":"0x0000000000000000000000000000000000000dad","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000000"]}],"index":1}]}}}`,
216+
want: `{"data":{"block":{"number":1,"transactions":[{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x64","hash":"0x46933b8a43e70320bb41910f015c4b2aded1caaba32b55b56054e4d1811d06d6","type":0,"accessList":[],"index":0},{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x32","hash":"0x03682ed7cc9cf9e9fa3bb6f58a62d6a350c09ec4d22b71b884503ae469e8640b","type":1,"accessList":[{"address":"0x0000000000000000000000000000000000000dad","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000000"]}],"index":1},{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x32","hash":"0x22f565cfeb33d5e6f81c8923ef0633a49fef0848a089a6d8564b655d5605fb13","type":2,"accessList":[],"index":2}]}}}`,
180217
code: 200,
181218
},
182219
} {
@@ -330,13 +367,23 @@ func createGQLServiceWithTransactions(t *testing.T, stack *node.Node) {
330367
StorageKeys: []common.Hash{{0}},
331368
}},
332369
})
370+
dynamicTx, _ := types.SignNewTx(key, signer, &types.DynamicFeeTx{
371+
ChainID: ethConf.Genesis.Config.ChainID,
372+
Nonce: uint64(2),
373+
To: &dad,
374+
Gas: 50000,
375+
GasFeeCap: big.NewInt(30000),
376+
GasTipCap: big.NewInt(10),
377+
Value: big.NewInt(50),
378+
})
333379

334380
// Create some blocks and import them
335381
chain, _ := core.GenerateChain(params.IstanbulEHFTestChainConfig, ethBackend.BlockChain().Genesis(),
336382
mockEngine.NewFaker(), ethBackend.ChainDb(), 1, func(i int, b *core.BlockGen) {
337383
b.SetCoinbase(common.Address{1})
338384
b.AddTx(legacyTx)
339385
b.AddTx(envelopTx)
386+
b.AddTx(dynamicTx)
340387
})
341388

342389
_, err = ethBackend.BlockChain().InsertChain(chain)

0 commit comments

Comments
 (0)