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