github.com/MetalBlockchain/subnet-evm@v0.4.9/ethclient/ethclient.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2016 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 // Package ethclient provides a client for the Ethereum RPC API. 28 package ethclient 29 30 import ( 31 "context" 32 "encoding/json" 33 "errors" 34 "fmt" 35 "math/big" 36 37 "github.com/MetalBlockchain/metalgo/ids" 38 "github.com/MetalBlockchain/subnet-evm/accounts/abi/bind" 39 "github.com/MetalBlockchain/subnet-evm/core/types" 40 "github.com/MetalBlockchain/subnet-evm/interfaces" 41 "github.com/MetalBlockchain/subnet-evm/rpc" 42 "github.com/ethereum/go-ethereum/common" 43 "github.com/ethereum/go-ethereum/common/hexutil" 44 ) 45 46 // Verify that Client implements required interfaces 47 var ( 48 _ bind.AcceptedContractCaller = (*client)(nil) 49 _ bind.ContractBackend = (*client)(nil) 50 _ bind.ContractFilterer = (*client)(nil) 51 _ bind.ContractTransactor = (*client)(nil) 52 _ bind.DeployBackend = (*client)(nil) 53 54 _ interfaces.ChainReader = (*client)(nil) 55 _ interfaces.ChainStateReader = (*client)(nil) 56 _ interfaces.TransactionReader = (*client)(nil) 57 _ interfaces.TransactionSender = (*client)(nil) 58 _ interfaces.ContractCaller = (*client)(nil) 59 _ interfaces.GasEstimator = (*client)(nil) 60 _ interfaces.GasPricer = (*client)(nil) 61 _ interfaces.LogFilterer = (*client)(nil) 62 _ interfaces.AcceptedStateReader = (*client)(nil) 63 _ interfaces.AcceptedContractCaller = (*client)(nil) 64 65 _ Client = (*client)(nil) 66 ) 67 68 // Client defines interface for typed wrappers for the Ethereum RPC API. 69 type Client interface { 70 Close() 71 ChainID(context.Context) (*big.Int, error) 72 BlockByHash(context.Context, common.Hash) (*types.Block, error) 73 BlockByNumber(context.Context, *big.Int) (*types.Block, error) 74 BlockNumber(context.Context) (uint64, error) 75 HeaderByHash(context.Context, common.Hash) (*types.Header, error) 76 HeaderByNumber(context.Context, *big.Int) (*types.Header, error) 77 TransactionByHash(context.Context, common.Hash) (tx *types.Transaction, isPending bool, err error) 78 TransactionSender(context.Context, *types.Transaction, common.Hash, uint) (common.Address, error) 79 TransactionCount(context.Context, common.Hash) (uint, error) 80 TransactionInBlock(context.Context, common.Hash, uint) (*types.Transaction, error) 81 TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) 82 SyncProgress(ctx context.Context) error 83 SubscribeNewAcceptedTransactions(context.Context, chan<- *common.Hash) (interfaces.Subscription, error) 84 SubscribeNewPendingTransactions(context.Context, chan<- *common.Hash) (interfaces.Subscription, error) 85 SubscribeNewHead(context.Context, chan<- *types.Header) (interfaces.Subscription, error) 86 NetworkID(context.Context) (*big.Int, error) 87 BalanceAt(context.Context, common.Address, *big.Int) (*big.Int, error) 88 AssetBalanceAt(context.Context, common.Address, ids.ID, *big.Int) (*big.Int, error) 89 StorageAt(context.Context, common.Address, common.Hash, *big.Int) ([]byte, error) 90 CodeAt(context.Context, common.Address, *big.Int) ([]byte, error) 91 NonceAt(context.Context, common.Address, *big.Int) (uint64, error) 92 FilterLogs(context.Context, interfaces.FilterQuery) ([]types.Log, error) 93 SubscribeFilterLogs(context.Context, interfaces.FilterQuery, chan<- types.Log) (interfaces.Subscription, error) 94 AcceptedCodeAt(context.Context, common.Address) ([]byte, error) 95 AcceptedNonceAt(context.Context, common.Address) (uint64, error) 96 AcceptedCallContract(context.Context, interfaces.CallMsg) ([]byte, error) 97 CallContract(context.Context, interfaces.CallMsg, *big.Int) ([]byte, error) 98 CallContractAtHash(ctx context.Context, msg interfaces.CallMsg, blockHash common.Hash) ([]byte, error) 99 SuggestGasPrice(context.Context) (*big.Int, error) 100 SuggestGasTipCap(context.Context) (*big.Int, error) 101 FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*interfaces.FeeHistory, error) 102 EstimateGas(context.Context, interfaces.CallMsg) (uint64, error) 103 EstimateBaseFee(context.Context) (*big.Int, error) 104 SendTransaction(context.Context, *types.Transaction) error 105 } 106 107 // client defines implementation for typed wrappers for the Ethereum RPC API. 108 type client struct { 109 c *rpc.Client 110 } 111 112 // Dial connects a client to the given URL. 113 func Dial(rawurl string) (Client, error) { 114 return DialContext(context.Background(), rawurl) 115 } 116 117 func DialContext(ctx context.Context, rawurl string) (Client, error) { 118 c, err := rpc.DialContext(ctx, rawurl) 119 if err != nil { 120 return nil, err 121 } 122 return NewClient(c), nil 123 } 124 125 // NewClient creates a client that uses the given RPC client. 126 func NewClient(c *rpc.Client) Client { 127 return &client{c} 128 } 129 130 func (ec *client) Close() { 131 ec.c.Close() 132 } 133 134 // Blockchain Access 135 136 // ChainID retrieves the current chain ID for transaction replay protection. 137 func (ec *client) ChainID(ctx context.Context) (*big.Int, error) { 138 var result hexutil.Big 139 err := ec.c.CallContext(ctx, &result, "eth_chainId") 140 if err != nil { 141 return nil, err 142 } 143 return (*big.Int)(&result), err 144 } 145 146 // BlockByHash returns the given full block. 147 // 148 // Note that loading full blocks requires two requests. Use HeaderByHash 149 // if you don't need all transactions or uncle headers. 150 func (ec *client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 151 return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) 152 } 153 154 // BlockByNumber returns a block from the current canonical chain. If number is nil, the 155 // latest known block is returned. 156 // 157 // Note that loading full blocks requires two requests. Use HeaderByNumber 158 // if you don't need all transactions or uncle headers. 159 func (ec *client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 160 return ec.getBlock(ctx, "eth_getBlockByNumber", ToBlockNumArg(number), true) 161 } 162 163 // BlockNumber returns the most recent block number 164 func (ec *client) BlockNumber(ctx context.Context) (uint64, error) { 165 var result hexutil.Uint64 166 err := ec.c.CallContext(ctx, &result, "eth_blockNumber") 167 return uint64(result), err 168 } 169 170 type rpcBlock struct { 171 Hash common.Hash `json:"hash"` 172 Transactions []rpcTransaction `json:"transactions"` 173 UncleHashes []common.Hash `json:"uncles"` 174 Version uint32 `json:"version"` 175 BlockExtraData *hexutil.Bytes `json:"blockExtraData"` 176 } 177 178 func (ec *client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { 179 var raw json.RawMessage 180 err := ec.c.CallContext(ctx, &raw, method, args...) 181 if err != nil { 182 return nil, err 183 } else if len(raw) == 0 { 184 return nil, interfaces.NotFound 185 } 186 // Decode header and transactions. 187 var head *types.Header 188 var body rpcBlock 189 if err := json.Unmarshal(raw, &head); err != nil { 190 return nil, err 191 } 192 if err := json.Unmarshal(raw, &body); err != nil { 193 return nil, err 194 } 195 // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. 196 if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { 197 return nil, fmt.Errorf("server returned non-empty uncle list but block header indicates no uncles") 198 } 199 if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { 200 return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") 201 } 202 if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { 203 return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") 204 } 205 if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { 206 return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") 207 } 208 // Load uncles because they are not included in the block response. 209 var uncles []*types.Header 210 if len(body.UncleHashes) > 0 { 211 uncles = make([]*types.Header, len(body.UncleHashes)) 212 reqs := make([]rpc.BatchElem, len(body.UncleHashes)) 213 for i := range reqs { 214 reqs[i] = rpc.BatchElem{ 215 Method: "eth_getUncleByBlockHashAndIndex", 216 Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))}, 217 Result: &uncles[i], 218 } 219 } 220 if err := ec.c.BatchCallContext(ctx, reqs); err != nil { 221 return nil, err 222 } 223 for i := range reqs { 224 if reqs[i].Error != nil { 225 return nil, reqs[i].Error 226 } 227 if uncles[i] == nil { 228 return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:]) 229 } 230 } 231 } 232 // Fill the sender cache of transactions in the block. 233 txs := make([]*types.Transaction, len(body.Transactions)) 234 for i, tx := range body.Transactions { 235 if tx.From != nil { 236 setSenderFromServer(tx.tx, *tx.From, body.Hash) 237 } 238 txs[i] = tx.tx 239 } 240 return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil 241 } 242 243 // HeaderByHash returns the block header with the given hash. 244 func (ec *client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 245 var head *types.Header 246 err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) 247 if err == nil && head == nil { 248 err = interfaces.NotFound 249 } 250 return head, err 251 } 252 253 // HeaderByNumber returns a block header from the current canonical chain. If number is 254 // nil, the latest known header is returned. 255 func (ec *client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 256 var head *types.Header 257 err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", ToBlockNumArg(number), false) 258 if err == nil && head == nil { 259 err = interfaces.NotFound 260 } 261 return head, err 262 } 263 264 type rpcTransaction struct { 265 tx *types.Transaction 266 txExtraInfo 267 } 268 269 type txExtraInfo struct { 270 BlockNumber *string `json:"blockNumber,omitempty"` 271 BlockHash *common.Hash `json:"blockHash,omitempty"` 272 From *common.Address `json:"from,omitempty"` 273 } 274 275 func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { 276 if err := json.Unmarshal(msg, &tx.tx); err != nil { 277 return err 278 } 279 return json.Unmarshal(msg, &tx.txExtraInfo) 280 } 281 282 // TransactionByHash returns the transaction with the given hash. 283 func (ec *client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { 284 var json *rpcTransaction 285 err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash) 286 if err != nil { 287 return nil, false, err 288 } else if json == nil { 289 return nil, false, interfaces.NotFound 290 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 291 return nil, false, fmt.Errorf("server returned transaction without signature") 292 } 293 if json.From != nil && json.BlockHash != nil { 294 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 295 } 296 return json.tx, json.BlockNumber == nil, nil 297 } 298 299 // TransactionSender returns the sender address of the given transaction. The transaction 300 // must be known to the remote node and included in the blockchain at the given block and 301 // index. The sender is the one derived by the protocol at the time of inclusion. 302 // 303 // There is a fast-path for transactions retrieved by TransactionByHash and 304 // TransactionInBlock. Getting their sender address can be done without an RPC interaction. 305 func (ec *client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { 306 // Try to load the address from the cache. 307 sender, err := types.Sender(&senderFromServer{blockhash: block}, tx) 308 if err == nil { 309 return sender, nil 310 } 311 312 // It was not found in cache, ask the server. 313 var meta struct { 314 Hash common.Hash 315 From common.Address 316 } 317 if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil { 318 return common.Address{}, err 319 } 320 if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() { 321 return common.Address{}, errors.New("wrong inclusion block/index") 322 } 323 return meta.From, nil 324 } 325 326 // TransactionCount returns the total number of transactions in the given block. 327 func (ec *client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { 328 var num hexutil.Uint 329 err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash) 330 return uint(num), err 331 } 332 333 // TransactionInBlock returns a single transaction at index in the given block. 334 func (ec *client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { 335 var json *rpcTransaction 336 err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) 337 if err != nil { 338 return nil, err 339 } 340 if json == nil { 341 return nil, interfaces.NotFound 342 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 343 return nil, fmt.Errorf("server returned transaction without signature") 344 } 345 if json.From != nil && json.BlockHash != nil { 346 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 347 } 348 return json.tx, err 349 } 350 351 // TransactionReceipt returns the receipt of a transaction by transaction hash. 352 // Note that the receipt is not available for pending transactions. 353 func (ec *client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 354 var r *types.Receipt 355 err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) 356 if err == nil { 357 if r == nil { 358 return nil, interfaces.NotFound 359 } 360 } 361 return r, err 362 } 363 364 // SyncProgress retrieves the current progress of the sync algorithm. If there's 365 // no sync currently running, it returns nil. 366 func (ec *client) SyncProgress(ctx context.Context) error { 367 var ( 368 raw json.RawMessage 369 syncing bool 370 ) 371 372 if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil { 373 return err 374 } 375 // If not syncing, the response will be 'false'. To detect this 376 // we unmarshal into a boolean and return nil on success. 377 // If the chain is syncing, the engine will not forward the 378 // request to the chain and a non-nil err will be returned. 379 return json.Unmarshal(raw, &syncing) 380 } 381 382 // SubscribeNewAcceptedTransactions subscribes to notifications about the accepted transaction hashes on the given channel. 383 func (ec *client) SubscribeNewAcceptedTransactions(ctx context.Context, ch chan<- *common.Hash) (interfaces.Subscription, error) { 384 return ec.c.EthSubscribe(ctx, ch, "newAcceptedTransactions") 385 } 386 387 // SubscribeNewAcceptedTransactions subscribes to notifications about the accepted transaction hashes on the given channel. 388 func (ec *client) SubscribeNewPendingTransactions(ctx context.Context, ch chan<- *common.Hash) (interfaces.Subscription, error) { 389 return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") 390 } 391 392 // SubscribeNewHead subscribes to notifications about the current blockchain head 393 // on the given channel. 394 func (ec *client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (interfaces.Subscription, error) { 395 return ec.c.EthSubscribe(ctx, ch, "newHeads") 396 } 397 398 // State Access 399 400 // NetworkID returns the network ID (also known as the chain ID) for this chain. 401 func (ec *client) NetworkID(ctx context.Context) (*big.Int, error) { 402 version := new(big.Int) 403 var ver string 404 if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil { 405 return nil, err 406 } 407 if _, ok := version.SetString(ver, 10); !ok { 408 return nil, fmt.Errorf("invalid net_version result %q", ver) 409 } 410 return version, nil 411 } 412 413 // BalanceAt returns the wei balance of the given account. 414 // The block number can be nil, in which case the balance is taken from the latest known block. 415 func (ec *client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { 416 var result hexutil.Big 417 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, ToBlockNumArg(blockNumber)) 418 return (*big.Int)(&result), err 419 } 420 421 // AssetBalanceAt returns the [assetID] balance of the given account 422 // The block number can be nil, in which case the balance is taken from the latest known block. 423 func (ec *client) AssetBalanceAt(ctx context.Context, account common.Address, assetID ids.ID, blockNumber *big.Int) (*big.Int, error) { 424 var result hexutil.Big 425 err := ec.c.CallContext(ctx, &result, "eth_getAssetBalance", account, ToBlockNumArg(blockNumber), assetID) 426 return (*big.Int)(&result), err 427 } 428 429 // StorageAt returns the value of key in the contract storage of the given account. 430 // The block number can be nil, in which case the value is taken from the latest known block. 431 func (ec *client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { 432 var result hexutil.Bytes 433 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, ToBlockNumArg(blockNumber)) 434 return result, err 435 } 436 437 // CodeAt returns the contract code of the given account. 438 // The block number can be nil, in which case the code is taken from the latest known block. 439 func (ec *client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { 440 var result hexutil.Bytes 441 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, ToBlockNumArg(blockNumber)) 442 return result, err 443 } 444 445 // NonceAt returns the account nonce of the given account. 446 // The block number can be nil, in which case the nonce is taken from the latest known block. 447 func (ec *client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { 448 var result hexutil.Uint64 449 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, ToBlockNumArg(blockNumber)) 450 return uint64(result), err 451 } 452 453 // Filters 454 455 // FilterLogs executes a filter query. 456 func (ec *client) FilterLogs(ctx context.Context, q interfaces.FilterQuery) ([]types.Log, error) { 457 var result []types.Log 458 arg, err := toFilterArg(q) 459 if err != nil { 460 return nil, err 461 } 462 err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg) 463 return result, err 464 } 465 466 // SubscribeFilterLogs subscribes to the results of a streaming filter query. 467 func (ec *client) SubscribeFilterLogs(ctx context.Context, q interfaces.FilterQuery, ch chan<- types.Log) (interfaces.Subscription, error) { 468 arg, err := toFilterArg(q) 469 if err != nil { 470 return nil, err 471 } 472 return ec.c.EthSubscribe(ctx, ch, "logs", arg) 473 } 474 475 func toFilterArg(q interfaces.FilterQuery) (interface{}, error) { 476 arg := map[string]interface{}{ 477 "address": q.Addresses, 478 "topics": q.Topics, 479 } 480 if q.BlockHash != nil { 481 arg["blockHash"] = *q.BlockHash 482 if q.FromBlock != nil || q.ToBlock != nil { 483 return nil, fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock") 484 } 485 } else { 486 if q.FromBlock == nil { 487 arg["fromBlock"] = "0x0" 488 } else { 489 arg["fromBlock"] = ToBlockNumArg(q.FromBlock) 490 } 491 arg["toBlock"] = ToBlockNumArg(q.ToBlock) 492 } 493 return arg, nil 494 } 495 496 // AcceptedCodeAt returns the contract code of the given account in the accepted state. 497 func (ec *client) AcceptedCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 498 return ec.CodeAt(ctx, account, nil) 499 } 500 501 // AcceptedNonceAt returns the account nonce of the given account in the accepted state. 502 // This is the nonce that should be used for the next transaction. 503 func (ec *client) AcceptedNonceAt(ctx context.Context, account common.Address) (uint64, error) { 504 return ec.NonceAt(ctx, account, nil) 505 } 506 507 // AcceptedCallContract executes a message call transaction in the accepted 508 // state. 509 func (ec *client) AcceptedCallContract(ctx context.Context, msg interfaces.CallMsg) ([]byte, error) { 510 return ec.CallContract(ctx, msg, nil) 511 } 512 513 // Contract Calling 514 515 // CallContract executes a message call transaction, which is directly executed in the VM 516 // of the node, but never mined into the blockchain. 517 // 518 // blockNumber selects the block height at which the call runs. It can be nil, in which 519 // case the code is taken from the latest known block. Note that state from very old 520 // blocks might not be available. 521 func (ec *client) CallContract(ctx context.Context, msg interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) { 522 var hex hexutil.Bytes 523 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), ToBlockNumArg(blockNumber)) 524 if err != nil { 525 return nil, err 526 } 527 return hex, nil 528 } 529 530 // CallContractAtHash is almost the same as CallContract except that it selects 531 // the block by block hash instead of block height. 532 func (ec *client) CallContractAtHash(ctx context.Context, msg interfaces.CallMsg, blockHash common.Hash) ([]byte, error) { 533 var hex hexutil.Bytes 534 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) 535 if err != nil { 536 return nil, err 537 } 538 return hex, nil 539 } 540 541 // SuggestGasPrice retrieves the currently suggested gas price to allow a timely 542 // execution of a transaction. 543 func (ec *client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 544 var hex hexutil.Big 545 if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil { 546 return nil, err 547 } 548 return (*big.Int)(&hex), nil 549 } 550 551 // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to 552 // allow a timely execution of a transaction. 553 func (ec *client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 554 var hex hexutil.Big 555 if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil { 556 return nil, err 557 } 558 return (*big.Int)(&hex), nil 559 } 560 561 type feeHistoryResultMarshaling struct { 562 OldestBlock *hexutil.Big `json:"oldestBlock"` 563 Reward [][]*hexutil.Big `json:"reward,omitempty"` 564 BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` 565 GasUsedRatio []float64 `json:"gasUsedRatio"` 566 } 567 568 // FeeHistory retrieves the fee market history. 569 func (ec *client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*interfaces.FeeHistory, error) { 570 var res feeHistoryResultMarshaling 571 if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), ToBlockNumArg(lastBlock), rewardPercentiles); err != nil { 572 return nil, err 573 } 574 reward := make([][]*big.Int, len(res.Reward)) 575 for i, r := range res.Reward { 576 reward[i] = make([]*big.Int, len(r)) 577 for j, r := range r { 578 reward[i][j] = (*big.Int)(r) 579 } 580 } 581 baseFee := make([]*big.Int, len(res.BaseFee)) 582 for i, b := range res.BaseFee { 583 baseFee[i] = (*big.Int)(b) 584 } 585 return &interfaces.FeeHistory{ 586 OldestBlock: (*big.Int)(res.OldestBlock), 587 Reward: reward, 588 BaseFee: baseFee, 589 GasUsedRatio: res.GasUsedRatio, 590 }, nil 591 } 592 593 // EstimateGas tries to estimate the gas needed to execute a specific transaction based on 594 // the current pending state of the backend blockchain. There is no guarantee that this is 595 // the true gas limit requirement as other transactions may be added or removed by miners, 596 // but it should provide a basis for setting a reasonable default. 597 func (ec *client) EstimateGas(ctx context.Context, msg interfaces.CallMsg) (uint64, error) { 598 var hex hexutil.Uint64 599 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) 600 if err != nil { 601 return 0, err 602 } 603 return uint64(hex), nil 604 } 605 606 // EstimateBaseFee tries to estimate the base fee for the next block if it were created 607 // immediately. There is no guarantee that this will be the base fee used in the next block 608 // or that the next base fee will be higher or lower than the returned value. 609 func (ec *client) EstimateBaseFee(ctx context.Context) (*big.Int, error) { 610 var hex hexutil.Big 611 err := ec.c.CallContext(ctx, &hex, "eth_baseFee") 612 if err != nil { 613 return nil, err 614 } 615 return (*big.Int)(&hex), nil 616 } 617 618 // SendTransaction injects a signed transaction into the pending pool for execution. 619 // 620 // If the transaction was a contract creation use the TransactionReceipt method to get the 621 // contract address after the transaction has been mined. 622 func (ec *client) SendTransaction(ctx context.Context, tx *types.Transaction) error { 623 data, err := tx.MarshalBinary() 624 if err != nil { 625 return err 626 } 627 return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) 628 } 629 630 func ToBlockNumArg(number *big.Int) string { 631 // The Ethereum implementation uses a different mapping from 632 // negative numbers to special strings (latest, pending) then is 633 // used on its server side. See rpc/types.go for the comparison. 634 // In Subnet EVM, latest, pending, and accepted are all treated the same 635 // therefore, if [number] is nil or a negative number in [-3, -1] 636 // we want the latest accepted block 637 if number == nil { 638 return "latest" 639 } 640 low := big.NewInt(-3) 641 high := big.NewInt(-1) 642 if number.Cmp(low) >= 0 && number.Cmp(high) <= 0 { 643 return "latest" 644 } 645 return hexutil.EncodeBig(number) 646 } 647 648 func toCallArg(msg interfaces.CallMsg) interface{} { 649 arg := map[string]interface{}{ 650 "from": msg.From, 651 "to": msg.To, 652 } 653 if len(msg.Data) > 0 { 654 arg["data"] = hexutil.Bytes(msg.Data) 655 } 656 if msg.Value != nil { 657 arg["value"] = (*hexutil.Big)(msg.Value) 658 } 659 if msg.Gas != 0 { 660 arg["gas"] = hexutil.Uint64(msg.Gas) 661 } 662 if msg.GasPrice != nil { 663 arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) 664 } 665 return arg 666 }