-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EvmFeeEstimator return Optimistic Rollup's L1BaseFee #10557
Conversation
I see that you haven't updated any README files. Would it make sense to do so? |
Running downstream job at https://github.com/smartcontractkit/operator-ui/actions/runs/6118401967 |
Running downstream job at https://github.com/smartcontractkit/operator-ui/actions/runs/6134940125 |
Running downstream job at https://github.com/smartcontractkit/operator-ui/actions/runs/6134995445 |
Running downstream job at https://github.com/smartcontractkit/operator-ui/actions/runs/6135066158 |
Running downstream job at https://github.com/smartcontractkit/operator-ui/actions/runs/6135119080 |
case config.ChainArbitrum: | ||
address = ArbGasInfoAddress | ||
selector = ArbGasInfo_getL1BaseFeeEstimate | ||
case config.ChainOptimismBedrock: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since Base also uses OptimismBedorck chaintype, can we confirm the address and the hex code are the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, Base uses the same precompiles as Optimism: https://basescan.org/address/0x420000000000000000000000000000000000000F#readProxyContract
@@ -4,6 +4,7 @@ import ( | |||
"context" | |||
|
|||
"github.com/pkg/errors" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: revert this change, and keep this file untouched
core/chains/evm/gas/models.go
Outdated
} | ||
} | ||
|
||
func (e WrappedEvmEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint32, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint32, err error) { | ||
func NewWrappedEvmEstimatorWithL1Oracle(e EvmEstimator, eip1559Enabled bool, o chainoracles.L1Oracle) EvmFeeEstimator { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to create this new function.
Just add the L1Oracle param to the existing NewWrappedEvmEstimator().
For chains that don't support the L1Oracle, just pass nil there.
address = OPGasOracleAddress | ||
selector = OPGasOracle_l1BaseFee | ||
default: | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you are calling this NewL1GasPriceOracle() only for chains that support it, the default case here should just call panic().
This will help surface up a misconfig or error faster.
defer close(o.chDone) | ||
|
||
t := o.refresh() | ||
close(o.chInitialised) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of from here, close this from within refresh(), once we successfully are able to set l1GasPrice there.
This way, this component is in started mode only after it fetches a valid l1GasPrice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Start() call is blocked on the chInitialised
channel, so we need to close it regardless of fetching prices (refresh()
) was successful or not right, closing it once here makes sense to me. This pattern is same in L2Suggested and Arbitrum estimators.
} | ||
|
||
if len(b) != 32 { // returns uint256; | ||
o.logger.Warnf("return data length (%d) different than expected (%d)", len(b), 32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a critical error. It indicates the response format has changed.
Data: common.Hex2Bytes(o.selector), | ||
}, big.NewInt(-1)) | ||
if err != nil { | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an error log here too
errOracle = e.l1Oracle.Ready() | ||
} | ||
|
||
if errEVM != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block of code can happen before even calling l1Oracle.Ready()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it'd only execute either when e.l1Oracle
is nil, or e.l1Oracle.Ready()
has been called. The drawback is if EvmEstimator
and l1Oracle
both error, only errEVM
will be surfaced. I think that's fine since it doesn't alter the outcome and EvmEstimator
is the more critical component.
b, err := o.client.CallContract(ctx, ethereum.CallMsg{ | ||
To: &precompile, | ||
Data: common.Hex2Bytes(o.selector), | ||
}, big.NewInt(-1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be nil
instead. Not sure why on Arbitrum Estimator is also -1
pollPeriod: PollPeriod, | ||
logger: lggr.Named(fmt.Sprintf("L1GasPriceOracle(%s)", chainType)), | ||
address: address, | ||
selector: selector, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about call
instead, since this is a hex-encoded call? Selector doesn't provide much context.
@@ -0,0 +1,176 @@ | |||
package chainoracles |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Just wondering, if this name is appropriate.
This seems to be a package for Rollups.
Could rollups be a better name?
|
||
var supportedChainTypes = []config.ChainType{config.ChainArbitrum, config.ChainOptimismBedrock} | ||
|
||
func IsL1OracleChain(chainType config.ChainType) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name can confuse someone into thinking if this chain itself is an L1 chain.
Is this a better name: IsRollupWithL1Support.
// For example, on Optimistic Rollups, this oracle can return rollup-specific l1BaseFee | ||
// | ||
//go:generate mockery --quiet --name L1Oracle --output ./mocks/ --case=underscore | ||
type L1Oracle interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about renaming to UnderlyingL1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer L1Oracle
since it is not actually calling the underlying L1, it is fetching from the L1 oracle contract provided by the L2
type L1Oracle interface { | ||
services.ServiceCtx | ||
|
||
L1GasPrice(ctx context.Context) (*assets.Wei, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the interface itself is named L1..., this function doesn't need to repeat it. Just say GasPrice()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good. Just asked a few question on the right namings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Prashant on the names. Other than that LGTM
SonarQube Quality Gate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot!
In CCIP, when user sends a message from Chain A -> Chain B, the OnRamp contract on Chain A needs to calculate the tx cost on Chain B in order to charge user such cost.
This requires OnRamp on Chain A to know Chain B's tx price components. When Chain B is an optimistic rollup, Chain A needs to know Chain B's l1GasPrice, in addition to regular gasPrice. This PR proposes to extend
EvmFeeEstimator
to return l1GasPrice, by adding a L1Oracle service intoWrappedEvmEstimator
Inside CCIP, we can consume it as