Skip to content

Commit

Permalink
use estimation even if header fetching fails -- in that case don't ap…
Browse files Browse the repository at this point in the history
…ply congestion-based buffer; treat buffer as adjustment instead of increase percentage; update readme
  • Loading branch information
Tofel committed May 20, 2024
1 parent d39f253 commit 32f4658
Show file tree
Hide file tree
Showing 4 changed files with 1,041 additions and 90 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,22 +355,27 @@ All values are multiplied by the adjustment factor, which is calculated based on
case Priority_Slow:
return 0.8
```
For fast transactions we will increase gas price by 20%, for standard we will use the value as is and for slow we will decrease it by 20%.

##### Buffer precents
##### Buffer percents
We further adjust the gas price by adding a buffer to it, based on congestion rate:
```go
case Congestion_Low:
return 0.10, nil
return 1.10, nil
case Congestion_Medium:
return 0.20, nil
return 1.20, nil
case Congestion_High:
return 0.30, nil
case Congestion_Degen:
return 0.40, nil
return 1.30, nil
case Congestion_VeryHigh:
return 1.40, nil
```

For low congestion rate we will increase gas price by 10%, for medium by 20%, for high by 30% and for very high by 40%.

We cache block header data in an in-memory cache, so we don't have to fetch it every time we estimate gas. The cache has capacity equal to `gas_price_estimation_blocks` and every time we add a new element, we remove one that is least frequently used and oldest (with block number being a constant and chain always moving forward it makes no sense to keep old blocks).

It's important to know that in order to use congestion metrics we need to fetch at least 80% of the requested blocks. If that fails, we will skip this part of the estimation and only adjust the gas price based on priority.

For both transaction types if any of the steps fails, we fallback to hardcoded values.

### Experimental features
Expand Down
25 changes: 25 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,31 @@ func (m *Client) configureTransactionOpts(
return opts
}

// ContractLoader is a helper struct for loading contracts
type ContractLoader[T any] struct {
Client *Client
}

// NewContractLoader creates a new contract loader
func NewContractLoader[T any](client *Client) *ContractLoader[T] {
return &ContractLoader[T]{
Client: client,
}
}

// LoadContract loads contract by name, address, ABI loader and wrapper init function, it adds contract ABI to Seth Contract Store and address to Contract Map. Thanks to that we can easily
// trace and debug interactions with the contract. Signatures of functions passed to this method were chosen to conform to Geth wrappers' GetAbi() and NewXXXContract() functions.
func (cl *ContractLoader[T]) LoadContract(name string, address common.Address, abiLoadFn func() (*abi.ABI, error), wrapperInitFn func(common.Address, bind.ContractBackend) (*T, error)) (*T, error) {
abiData, err := abiLoadFn()
if err != nil {
return new(T), err
}
cl.Client.ContractStore.AddABI(name, *abiData)
cl.Client.ContractAddressToNameMap.AddContract(address.Hex(), name)

return wrapperInitFn(address, cl.Client.Client)
}

// DeployContract deploys contract using ABI and bytecode passed to it, waits for transaction to be minted and contract really
// available at the address, so that when the method returns it's safe to interact with it. It also saves the contract address and ABI name
// to the contract map, so that we can use that, when tracing transactions. It is suggested to use name identical to the name of the contract Solidity file.
Expand Down

0 comments on commit 32f4658

Please sign in to comment.