-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ChainWriter EVM GetFeeComponents implementation (#13413)
* ChainWriter EVM GetFeeComponents implementation * Fixed Write Target CW initialization * added changeset * Added ChainWriter tests * linting fix * Updated comment * Moved MaxGasPrice to CW Config * Changed ExecGasEstimator to CWGasEstimator * removed tests from this PR * Added comments and updated cw struct * renamed gasPriceWei to evmFee * Added more specific error for gasPrice == nil * Update core/services/relay/evm/chain_writer.go Co-authored-by: Jordan Krage <[email protected]> * Added tests back in * Reverted to testing EvmFeeEstimator rather than EvmEstimator * reordered imports on CW * Added maxGasPrice default * review requests * Update core/services/relay/evm/write_target.go Co-authored-by: Jordan Krage <[email protected]> * Fixed maxGasPrice type * changed maxGasPrice to assets.Wei * mocked gasEstimator --------- Co-authored-by: Jordan Krage <[email protected]>
- Loading branch information
1 parent
d736d9e
commit 9e733a0
Showing
6 changed files
with
231 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"chainlink": minor | ||
--- | ||
|
||
#added EVM implementation of GetFeeComponents function for ChainWriter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package evm | ||
|
||
import ( | ||
"fmt" | ||
"math/big" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/smartcontractkit/chainlink-common/pkg/types" | ||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" | ||
evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" | ||
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" | ||
gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" | ||
rollupmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" | ||
txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" | ||
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" | ||
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils" | ||
"github.com/smartcontractkit/chainlink/v2/core/logger" | ||
relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" | ||
) | ||
|
||
func TestChainWriter(t *testing.T) { | ||
lggr := logger.TestLogger(t) | ||
ctx := testutils.Context(t) | ||
|
||
txm := txmmocks.NewMockEvmTxManager(t) | ||
client := evmclimocks.NewClient(t) | ||
ge := gasmocks.NewEvmFeeEstimator(t) | ||
l1Oracle := rollupmocks.NewL1Oracle(t) | ||
|
||
chainWriterConfig := newBaseChainWriterConfig() | ||
cw, err := NewChainWriterService(lggr, client, txm, ge, chainWriterConfig) | ||
|
||
require.NoError(t, err) | ||
|
||
t.Run("Initialization", func(t *testing.T) { | ||
t.Run("Fails with invalid ABI", func(t *testing.T) { | ||
baseConfig := newBaseChainWriterConfig() | ||
invalidAbiConfig := modifyChainWriterConfig(baseConfig, func(cfg *relayevmtypes.ChainWriterConfig) { | ||
cfg.Contracts["forwarder"].ContractABI = "" | ||
}) | ||
_, err = NewChainWriterService(lggr, client, txm, ge, invalidAbiConfig) | ||
require.Error(t, err) | ||
}) | ||
|
||
t.Run("Fails with invalid method names", func(t *testing.T) { | ||
baseConfig := newBaseChainWriterConfig() | ||
invalidMethodNameConfig := modifyChainWriterConfig(baseConfig, func(cfg *relayevmtypes.ChainWriterConfig) { | ||
cfg.Contracts["forwarder"].Configs["report"].ChainSpecificName = "" | ||
}) | ||
_, err = NewChainWriterService(lggr, client, txm, ge, invalidMethodNameConfig) | ||
require.Error(t, err) | ||
}) | ||
}) | ||
|
||
t.Run("SubmitTransaction", func(t *testing.T) { | ||
// TODO: implement | ||
}) | ||
|
||
t.Run("GetFeeComponents", func(t *testing.T) { | ||
ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ | ||
Legacy: assets.NewWei(big.NewInt(1000000001)), | ||
DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), | ||
DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), | ||
}, uint64(0), nil).Twice() | ||
|
||
l1Oracle.On("GasPrice", mock.Anything).Return(assets.NewWei(big.NewInt(1000000004)), nil).Once() | ||
ge.On("L1Oracle", mock.Anything).Return(l1Oracle).Once() | ||
var feeComponents *types.ChainFeeComponents | ||
t.Run("Returns valid FeeComponents", func(t *testing.T) { | ||
feeComponents, err = cw.GetFeeComponents(ctx) | ||
require.NoError(t, err) | ||
assert.Equal(t, big.NewInt(1000000002), &feeComponents.ExecutionFee) | ||
assert.Equal(t, big.NewInt(1000000004), &feeComponents.DataAvailabilityFee) | ||
}) | ||
|
||
ge.On("L1Oracle", mock.Anything).Return(nil).Twice() | ||
|
||
t.Run("Returns valid FeeComponents with no L1Oracle", func(t *testing.T) { | ||
feeComponents, err = cw.GetFeeComponents(ctx) | ||
require.NoError(t, err) | ||
assert.Equal(t, big.NewInt(1000000002), &feeComponents.ExecutionFee) | ||
assert.Equal(t, big.NewInt(0), &feeComponents.DataAvailabilityFee) | ||
}) | ||
|
||
t.Run("Returns Legacy Fee in absence of Dynamic Fee", func(t *testing.T) { | ||
ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ | ||
Legacy: assets.NewWei(big.NewInt(1000000001)), | ||
DynamicFeeCap: nil, | ||
DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), | ||
}, uint64(0), nil).Once() | ||
feeComponents, err = cw.GetFeeComponents(ctx) | ||
require.NoError(t, err) | ||
assert.Equal(t, big.NewInt(1000000001), &feeComponents.ExecutionFee) | ||
assert.Equal(t, big.NewInt(0), &feeComponents.DataAvailabilityFee) | ||
}) | ||
|
||
t.Run("Fails when neither legacy or dynamic fee is available", func(t *testing.T) { | ||
ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ | ||
Legacy: nil, | ||
DynamicFeeCap: nil, | ||
DynamicTipCap: nil, | ||
}, uint64(0), nil).Once() | ||
|
||
_, err = cw.GetFeeComponents(ctx) | ||
require.Error(t, err) | ||
}) | ||
|
||
t.Run("Fails when GetFee returns an error", func(t *testing.T) { | ||
expectedErr := fmt.Errorf("GetFee error") | ||
ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ | ||
Legacy: nil, | ||
DynamicFeeCap: nil, | ||
DynamicTipCap: nil, | ||
}, uint64(0), expectedErr).Once() | ||
_, err = cw.GetFeeComponents(ctx) | ||
require.Equal(t, expectedErr, err) | ||
}) | ||
|
||
t.Run("Fails when L1Oracle returns error", func(t *testing.T) { | ||
ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ | ||
Legacy: assets.NewWei(big.NewInt(1000000001)), | ||
DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), | ||
DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), | ||
}, uint64(0), nil).Once() | ||
ge.On("L1Oracle", mock.Anything).Return(l1Oracle).Once() | ||
|
||
expectedErr := fmt.Errorf("l1Oracle error") | ||
l1Oracle.On("GasPrice", mock.Anything).Return(nil, expectedErr).Once() | ||
_, err = cw.GetFeeComponents(ctx) | ||
require.Equal(t, expectedErr, err) | ||
}) | ||
}) | ||
} | ||
|
||
// Helper functions to remove redundant creation of configs | ||
func newBaseChainWriterConfig() relayevmtypes.ChainWriterConfig { | ||
return relayevmtypes.ChainWriterConfig{ | ||
Contracts: map[string]*relayevmtypes.ContractConfig{ | ||
"forwarder": { | ||
// TODO: Use generic ABI / test contract rather than a keystone specific one | ||
ContractABI: forwarder.KeystoneForwarderABI, | ||
Configs: map[string]*relayevmtypes.ChainWriterDefinition{ | ||
"report": { | ||
ChainSpecificName: "report", | ||
Checker: "simulate", | ||
FromAddress: testutils.NewAddress(), | ||
GasLimit: 200_000, | ||
}, | ||
}, | ||
}, | ||
}, | ||
MaxGasPrice: assets.NewWeiI(1000000000000), | ||
} | ||
} | ||
|
||
func modifyChainWriterConfig(baseConfig relayevmtypes.ChainWriterConfig, modifyFn func(*relayevmtypes.ChainWriterConfig)) relayevmtypes.ChainWriterConfig { | ||
modifiedConfig := baseConfig | ||
modifyFn(&modifiedConfig) | ||
return modifiedConfig | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters