diff --git a/pkg/.mockery.yaml b/pkg/.mockery.yaml index 65783bbffb..d21e25ec36 100644 --- a/pkg/.mockery.yaml +++ b/pkg/.mockery.yaml @@ -86,3 +86,6 @@ packages: filename: "mock_{{ .InterfaceName | snakecase }}_test.go" interfaces: Emitter: + github.com/smartcontractkit/chainlink-evm/pkg/logpoller: + interfaces: + LogPoller: diff --git a/pkg/logpoller/mocks/log_poller.go b/pkg/logpoller/mocks/log_poller.go new file mode 100644 index 0000000000..3024b67cb3 --- /dev/null +++ b/pkg/logpoller/mocks/log_poller.go @@ -0,0 +1,1871 @@ +// Code generated by mockery v2.53.3. DO NOT EDIT. + +package mocks + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + logpoller "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + + mock "github.com/stretchr/testify/mock" + + query "github.com/smartcontractkit/chainlink-common/pkg/types/query" + + time "time" + + types "github.com/smartcontractkit/chainlink-evm/pkg/types" +) + +// LogPoller is an autogenerated mock type for the LogPoller type +type LogPoller struct { + mock.Mock +} + +type LogPoller_Expecter struct { + mock *mock.Mock +} + +func (_m *LogPoller) EXPECT() *LogPoller_Expecter { + return &LogPoller_Expecter{mock: &_m.Mock} +} + +// Close provides a mock function with no fields +func (_m *LogPoller) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type LogPoller_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *LogPoller_Expecter) Close() *LogPoller_Close_Call { + return &LogPoller_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *LogPoller_Close_Call) Run(run func()) *LogPoller_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_Close_Call) Return(_a0 error) *LogPoller_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Close_Call) RunAndReturn(run func() error) *LogPoller_Close_Call { + _c.Call.Return(run) + return _c +} + +// DeleteLogsAndBlocksAfter provides a mock function with given fields: ctx, start +func (_m *LogPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + ret := _m.Called(ctx, start) + + if len(ret) == 0 { + panic("no return value specified for DeleteLogsAndBlocksAfter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, start) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_DeleteLogsAndBlocksAfter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteLogsAndBlocksAfter' +type LogPoller_DeleteLogsAndBlocksAfter_Call struct { + *mock.Call +} + +// DeleteLogsAndBlocksAfter is a helper method to define mock.On call +// - ctx context.Context +// - start int64 +func (_e *LogPoller_Expecter) DeleteLogsAndBlocksAfter(ctx interface{}, start interface{}) *LogPoller_DeleteLogsAndBlocksAfter_Call { + return &LogPoller_DeleteLogsAndBlocksAfter_Call{Call: _e.mock.On("DeleteLogsAndBlocksAfter", ctx, start)} +} + +func (_c *LogPoller_DeleteLogsAndBlocksAfter_Call) Run(run func(ctx context.Context, start int64)) *LogPoller_DeleteLogsAndBlocksAfter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64)) + }) + return _c +} + +func (_c *LogPoller_DeleteLogsAndBlocksAfter_Call) Return(_a0 error) *LogPoller_DeleteLogsAndBlocksAfter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_DeleteLogsAndBlocksAfter_Call) RunAndReturn(run func(context.Context, int64) error) *LogPoller_DeleteLogsAndBlocksAfter_Call { + _c.Call.Return(run) + return _c +} + +// FilteredLogs provides a mock function with given fields: ctx, filter, limitAndSort, queryName +func (_m *LogPoller) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) { + ret := _m.Called(ctx, filter, limitAndSort, queryName) + + if len(ret) == 0 { + panic("no return value specified for FilteredLogs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []query.Expression, query.LimitAndSort, string) ([]logpoller.Log, error)); ok { + return rf(ctx, filter, limitAndSort, queryName) + } + if rf, ok := ret.Get(0).(func(context.Context, []query.Expression, query.LimitAndSort, string) []logpoller.Log); ok { + r0 = rf(ctx, filter, limitAndSort, queryName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []query.Expression, query.LimitAndSort, string) error); ok { + r1 = rf(ctx, filter, limitAndSort, queryName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_FilteredLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilteredLogs' +type LogPoller_FilteredLogs_Call struct { + *mock.Call +} + +// FilteredLogs is a helper method to define mock.On call +// - ctx context.Context +// - filter []query.Expression +// - limitAndSort query.LimitAndSort +// - queryName string +func (_e *LogPoller_Expecter) FilteredLogs(ctx interface{}, filter interface{}, limitAndSort interface{}, queryName interface{}) *LogPoller_FilteredLogs_Call { + return &LogPoller_FilteredLogs_Call{Call: _e.mock.On("FilteredLogs", ctx, filter, limitAndSort, queryName)} +} + +func (_c *LogPoller_FilteredLogs_Call) Run(run func(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string)) *LogPoller_FilteredLogs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]query.Expression), args[2].(query.LimitAndSort), args[3].(string)) + }) + return _c +} + +func (_c *LogPoller_FilteredLogs_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_FilteredLogs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_FilteredLogs_Call) RunAndReturn(run func(context.Context, []query.Expression, query.LimitAndSort, string) ([]logpoller.Log, error)) *LogPoller_FilteredLogs_Call { + _c.Call.Return(run) + return _c +} + +// FindLCA provides a mock function with given fields: ctx +func (_m *LogPoller) FindLCA(ctx context.Context) (*logpoller.Block, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for FindLCA") + } + + var r0 *logpoller.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*logpoller.Block, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *logpoller.Block); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_FindLCA_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindLCA' +type LogPoller_FindLCA_Call struct { + *mock.Call +} + +// FindLCA is a helper method to define mock.On call +// - ctx context.Context +func (_e *LogPoller_Expecter) FindLCA(ctx interface{}) *LogPoller_FindLCA_Call { + return &LogPoller_FindLCA_Call{Call: _e.mock.On("FindLCA", ctx)} +} + +func (_c *LogPoller_FindLCA_Call) Run(run func(ctx context.Context)) *LogPoller_FindLCA_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *LogPoller_FindLCA_Call) Return(_a0 *logpoller.Block, _a1 error) *LogPoller_FindLCA_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_FindLCA_Call) RunAndReturn(run func(context.Context) (*logpoller.Block, error)) *LogPoller_FindLCA_Call { + _c.Call.Return(run) + return _c +} + +// GetBlocksRange provides a mock function with given fields: ctx, numbers +func (_m *LogPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]logpoller.Block, error) { + ret := _m.Called(ctx, numbers) + + if len(ret) == 0 { + panic("no return value specified for GetBlocksRange") + } + + var r0 []logpoller.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []uint64) ([]logpoller.Block, error)); ok { + return rf(ctx, numbers) + } + if rf, ok := ret.Get(0).(func(context.Context, []uint64) []logpoller.Block); ok { + r0 = rf(ctx, numbers) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []uint64) error); ok { + r1 = rf(ctx, numbers) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_GetBlocksRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlocksRange' +type LogPoller_GetBlocksRange_Call struct { + *mock.Call +} + +// GetBlocksRange is a helper method to define mock.On call +// - ctx context.Context +// - numbers []uint64 +func (_e *LogPoller_Expecter) GetBlocksRange(ctx interface{}, numbers interface{}) *LogPoller_GetBlocksRange_Call { + return &LogPoller_GetBlocksRange_Call{Call: _e.mock.On("GetBlocksRange", ctx, numbers)} +} + +func (_c *LogPoller_GetBlocksRange_Call) Run(run func(ctx context.Context, numbers []uint64)) *LogPoller_GetBlocksRange_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]uint64)) + }) + return _c +} + +func (_c *LogPoller_GetBlocksRange_Call) Return(_a0 []logpoller.Block, _a1 error) *LogPoller_GetBlocksRange_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_GetBlocksRange_Call) RunAndReturn(run func(context.Context, []uint64) ([]logpoller.Block, error)) *LogPoller_GetBlocksRange_Call { + _c.Call.Return(run) + return _c +} + +// GetFilters provides a mock function with no fields +func (_m *LogPoller) GetFilters() map[string]logpoller.Filter { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetFilters") + } + + var r0 map[string]logpoller.Filter + if rf, ok := ret.Get(0).(func() map[string]logpoller.Filter); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]logpoller.Filter) + } + } + + return r0 +} + +// LogPoller_GetFilters_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFilters' +type LogPoller_GetFilters_Call struct { + *mock.Call +} + +// GetFilters is a helper method to define mock.On call +func (_e *LogPoller_Expecter) GetFilters() *LogPoller_GetFilters_Call { + return &LogPoller_GetFilters_Call{Call: _e.mock.On("GetFilters")} +} + +func (_c *LogPoller_GetFilters_Call) Run(run func()) *LogPoller_GetFilters_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_GetFilters_Call) Return(_a0 map[string]logpoller.Filter) *LogPoller_GetFilters_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_GetFilters_Call) RunAndReturn(run func() map[string]logpoller.Filter) *LogPoller_GetFilters_Call { + _c.Call.Return(run) + return _c +} + +// HasFilter provides a mock function with given fields: name +func (_m *LogPoller) HasFilter(name string) bool { + ret := _m.Called(name) + + if len(ret) == 0 { + panic("no return value specified for HasFilter") + } + + var r0 bool + if rf, ok := ret.Get(0).(func(string) bool); ok { + r0 = rf(name) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// LogPoller_HasFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HasFilter' +type LogPoller_HasFilter_Call struct { + *mock.Call +} + +// HasFilter is a helper method to define mock.On call +// - name string +func (_e *LogPoller_Expecter) HasFilter(name interface{}) *LogPoller_HasFilter_Call { + return &LogPoller_HasFilter_Call{Call: _e.mock.On("HasFilter", name)} +} + +func (_c *LogPoller_HasFilter_Call) Run(run func(name string)) *LogPoller_HasFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *LogPoller_HasFilter_Call) Return(_a0 bool) *LogPoller_HasFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_HasFilter_Call) RunAndReturn(run func(string) bool) *LogPoller_HasFilter_Call { + _c.Call.Return(run) + return _c +} + +// HealthReport provides a mock function with no fields +func (_m *LogPoller) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// LogPoller_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type LogPoller_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *LogPoller_Expecter) HealthReport() *LogPoller_HealthReport_Call { + return &LogPoller_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *LogPoller_HealthReport_Call) Run(run func()) *LogPoller_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_HealthReport_Call) Return(_a0 map[string]error) *LogPoller_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_HealthReport_Call) RunAndReturn(run func() map[string]error) *LogPoller_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Healthy provides a mock function with no fields +func (_m *LogPoller) Healthy() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Healthy") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_Healthy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Healthy' +type LogPoller_Healthy_Call struct { + *mock.Call +} + +// Healthy is a helper method to define mock.On call +func (_e *LogPoller_Expecter) Healthy() *LogPoller_Healthy_Call { + return &LogPoller_Healthy_Call{Call: _e.mock.On("Healthy")} +} + +func (_c *LogPoller_Healthy_Call) Run(run func()) *LogPoller_Healthy_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_Healthy_Call) Return(_a0 error) *LogPoller_Healthy_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Healthy_Call) RunAndReturn(run func() error) *LogPoller_Healthy_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogs provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValues, confs +func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, topicIndex, topicValues, confs) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, topicIndex, topicValues, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, topicIndex, topicValues, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, topicIndex, topicValues, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogs' +type LogPoller_IndexedLogs_Call struct { + *mock.Call +} + +// IndexedLogs is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - topicIndex int +// - topicValues []common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) IndexedLogs(ctx interface{}, eventSig interface{}, address interface{}, topicIndex interface{}, topicValues interface{}, confs interface{}) *LogPoller_IndexedLogs_Call { + return &LogPoller_IndexedLogs_Call{Call: _e.mock.On("IndexedLogs", ctx, eventSig, address, topicIndex, topicValues, confs)} +} + +func (_c *LogPoller_IndexedLogs_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs types.Confirmations)) *LogPoller_IndexedLogs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].([]common.Hash), args[5].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogs_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogs_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, []common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_IndexedLogs_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsByBlockRange provides a mock function with given fields: ctx, start, end, eventSig, address, topicIndex, topicValues +func (_m *LogPoller) IndexedLogsByBlockRange(ctx context.Context, start int64, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]logpoller.Log, error) { + ret := _m.Called(ctx, start, end, eventSig, address, topicIndex, topicValues) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsByBlockRange") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, common.Hash, common.Address, int, []common.Hash) ([]logpoller.Log, error)); ok { + return rf(ctx, start, end, eventSig, address, topicIndex, topicValues) + } + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, common.Hash, common.Address, int, []common.Hash) []logpoller.Log); ok { + r0 = rf(ctx, start, end, eventSig, address, topicIndex, topicValues) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, common.Hash, common.Address, int, []common.Hash) error); ok { + r1 = rf(ctx, start, end, eventSig, address, topicIndex, topicValues) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsByBlockRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsByBlockRange' +type LogPoller_IndexedLogsByBlockRange_Call struct { + *mock.Call +} + +// IndexedLogsByBlockRange is a helper method to define mock.On call +// - ctx context.Context +// - start int64 +// - end int64 +// - eventSig common.Hash +// - address common.Address +// - topicIndex int +// - topicValues []common.Hash +func (_e *LogPoller_Expecter) IndexedLogsByBlockRange(ctx interface{}, start interface{}, end interface{}, eventSig interface{}, address interface{}, topicIndex interface{}, topicValues interface{}) *LogPoller_IndexedLogsByBlockRange_Call { + return &LogPoller_IndexedLogsByBlockRange_Call{Call: _e.mock.On("IndexedLogsByBlockRange", ctx, start, end, eventSig, address, topicIndex, topicValues)} +} + +func (_c *LogPoller_IndexedLogsByBlockRange_Call) Run(run func(ctx context.Context, start int64, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash)) *LogPoller_IndexedLogsByBlockRange_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(common.Hash), args[4].(common.Address), args[5].(int), args[6].([]common.Hash)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsByBlockRange_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsByBlockRange_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsByBlockRange_Call) RunAndReturn(run func(context.Context, int64, int64, common.Hash, common.Address, int, []common.Hash) ([]logpoller.Log, error)) *LogPoller_IndexedLogsByBlockRange_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsByTxHash provides a mock function with given fields: ctx, eventSig, address, txHash +func (_m *LogPoller) IndexedLogsByTxHash(ctx context.Context, eventSig common.Hash, address common.Address, txHash common.Hash) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, txHash) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsByTxHash") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, common.Hash) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, common.Hash) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, txHash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, common.Hash) error); ok { + r1 = rf(ctx, eventSig, address, txHash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsByTxHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsByTxHash' +type LogPoller_IndexedLogsByTxHash_Call struct { + *mock.Call +} + +// IndexedLogsByTxHash is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - txHash common.Hash +func (_e *LogPoller_Expecter) IndexedLogsByTxHash(ctx interface{}, eventSig interface{}, address interface{}, txHash interface{}) *LogPoller_IndexedLogsByTxHash_Call { + return &LogPoller_IndexedLogsByTxHash_Call{Call: _e.mock.On("IndexedLogsByTxHash", ctx, eventSig, address, txHash)} +} + +func (_c *LogPoller_IndexedLogsByTxHash_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, txHash common.Hash)) *LogPoller_IndexedLogsByTxHash_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(common.Hash)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsByTxHash_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsByTxHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsByTxHash_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, common.Hash) ([]logpoller.Log, error)) *LogPoller_IndexedLogsByTxHash_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsCreatedAfter provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValues, after, confs +func (_m *LogPoller) IndexedLogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, topicIndex, topicValues, after, confs) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsCreatedAfter") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, topicIndex, topicValues, after, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsCreatedAfter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsCreatedAfter' +type LogPoller_IndexedLogsCreatedAfter_Call struct { + *mock.Call +} + +// IndexedLogsCreatedAfter is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - topicIndex int +// - topicValues []common.Hash +// - after time.Time +// - confs types.Confirmations +func (_e *LogPoller_Expecter) IndexedLogsCreatedAfter(ctx interface{}, eventSig interface{}, address interface{}, topicIndex interface{}, topicValues interface{}, after interface{}, confs interface{}) *LogPoller_IndexedLogsCreatedAfter_Call { + return &LogPoller_IndexedLogsCreatedAfter_Call{Call: _e.mock.On("IndexedLogsCreatedAfter", ctx, eventSig, address, topicIndex, topicValues, after, confs)} +} + +func (_c *LogPoller_IndexedLogsCreatedAfter_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, after time.Time, confs types.Confirmations)) *LogPoller_IndexedLogsCreatedAfter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].([]common.Hash), args[5].(time.Time), args[6].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsCreatedAfter_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsCreatedAfter_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsCreatedAfter_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, []common.Hash, time.Time, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_IndexedLogsCreatedAfter_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsTopicGreaterThan provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValueMin, confs +func (_m *LogPoller) IndexedLogsTopicGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, topicIndex, topicValueMin, confs) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsTopicGreaterThan") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, topicIndex, topicValueMin, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsTopicGreaterThan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsTopicGreaterThan' +type LogPoller_IndexedLogsTopicGreaterThan_Call struct { + *mock.Call +} + +// IndexedLogsTopicGreaterThan is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - topicIndex int +// - topicValueMin common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) IndexedLogsTopicGreaterThan(ctx interface{}, eventSig interface{}, address interface{}, topicIndex interface{}, topicValueMin interface{}, confs interface{}) *LogPoller_IndexedLogsTopicGreaterThan_Call { + return &LogPoller_IndexedLogsTopicGreaterThan_Call{Call: _e.mock.On("IndexedLogsTopicGreaterThan", ctx, eventSig, address, topicIndex, topicValueMin, confs)} +} + +func (_c *LogPoller_IndexedLogsTopicGreaterThan_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, confs types.Confirmations)) *LogPoller_IndexedLogsTopicGreaterThan_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].(common.Hash), args[5].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsTopicGreaterThan_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsTopicGreaterThan_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsTopicGreaterThan_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_IndexedLogsTopicGreaterThan_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsTopicRange provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs +func (_m *LogPoller) IndexedLogsTopicRange(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsTopicRange") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsTopicRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsTopicRange' +type LogPoller_IndexedLogsTopicRange_Call struct { + *mock.Call +} + +// IndexedLogsTopicRange is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - topicIndex int +// - topicValueMin common.Hash +// - topicValueMax common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) IndexedLogsTopicRange(ctx interface{}, eventSig interface{}, address interface{}, topicIndex interface{}, topicValueMin interface{}, topicValueMax interface{}, confs interface{}) *LogPoller_IndexedLogsTopicRange_Call { + return &LogPoller_IndexedLogsTopicRange_Call{Call: _e.mock.On("IndexedLogsTopicRange", ctx, eventSig, address, topicIndex, topicValueMin, topicValueMax, confs)} +} + +func (_c *LogPoller_IndexedLogsTopicRange_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValueMin common.Hash, topicValueMax common.Hash, confs types.Confirmations)) *LogPoller_IndexedLogsTopicRange_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].(common.Hash), args[5].(common.Hash), args[6].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsTopicRange_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsTopicRange_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsTopicRange_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_IndexedLogsTopicRange_Call { + _c.Call.Return(run) + return _c +} + +// IndexedLogsWithSigsExcluding provides a mock function with given fields: ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs +func (_m *LogPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address common.Address, eventSigA common.Hash, eventSigB common.Hash, topicIndex int, fromBlock int64, toBlock int64, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) + + if len(ret) == 0 { + panic("no return value specified for IndexedLogsWithSigsExcluding") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) error); ok { + r1 = rf(ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_IndexedLogsWithSigsExcluding_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IndexedLogsWithSigsExcluding' +type LogPoller_IndexedLogsWithSigsExcluding_Call struct { + *mock.Call +} + +// IndexedLogsWithSigsExcluding is a helper method to define mock.On call +// - ctx context.Context +// - address common.Address +// - eventSigA common.Hash +// - eventSigB common.Hash +// - topicIndex int +// - fromBlock int64 +// - toBlock int64 +// - confs types.Confirmations +func (_e *LogPoller_Expecter) IndexedLogsWithSigsExcluding(ctx interface{}, address interface{}, eventSigA interface{}, eventSigB interface{}, topicIndex interface{}, fromBlock interface{}, toBlock interface{}, confs interface{}) *LogPoller_IndexedLogsWithSigsExcluding_Call { + return &LogPoller_IndexedLogsWithSigsExcluding_Call{Call: _e.mock.On("IndexedLogsWithSigsExcluding", ctx, address, eventSigA, eventSigB, topicIndex, fromBlock, toBlock, confs)} +} + +func (_c *LogPoller_IndexedLogsWithSigsExcluding_Call) Run(run func(ctx context.Context, address common.Address, eventSigA common.Hash, eventSigB common.Hash, topicIndex int, fromBlock int64, toBlock int64, confs types.Confirmations)) *LogPoller_IndexedLogsWithSigsExcluding_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(common.Hash), args[3].(common.Hash), args[4].(int), args[5].(int64), args[6].(int64), args[7].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_IndexedLogsWithSigsExcluding_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_IndexedLogsWithSigsExcluding_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_IndexedLogsWithSigsExcluding_Call) RunAndReturn(run func(context.Context, common.Address, common.Hash, common.Hash, int, int64, int64, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_IndexedLogsWithSigsExcluding_Call { + _c.Call.Return(run) + return _c +} + +// LatestBlock provides a mock function with given fields: ctx +func (_m *LogPoller) LatestBlock(ctx context.Context) (logpoller.Block, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for LatestBlock") + } + + var r0 logpoller.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (logpoller.Block, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) logpoller.Block); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(logpoller.Block) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LatestBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestBlock' +type LogPoller_LatestBlock_Call struct { + *mock.Call +} + +// LatestBlock is a helper method to define mock.On call +// - ctx context.Context +func (_e *LogPoller_Expecter) LatestBlock(ctx interface{}) *LogPoller_LatestBlock_Call { + return &LogPoller_LatestBlock_Call{Call: _e.mock.On("LatestBlock", ctx)} +} + +func (_c *LogPoller_LatestBlock_Call) Run(run func(ctx context.Context)) *LogPoller_LatestBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *LogPoller_LatestBlock_Call) Return(_a0 logpoller.Block, _a1 error) *LogPoller_LatestBlock_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LatestBlock_Call) RunAndReturn(run func(context.Context) (logpoller.Block, error)) *LogPoller_LatestBlock_Call { + _c.Call.Return(run) + return _c +} + +// LatestBlockByEventSigsAddrsWithConfs provides a mock function with given fields: ctx, fromBlock, eventSigs, addresses, confs +func (_m *LogPoller) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations) (int64, error) { + ret := _m.Called(ctx, fromBlock, eventSigs, addresses, confs) + + if len(ret) == 0 { + panic("no return value specified for LatestBlockByEventSigsAddrsWithConfs") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) (int64, error)); ok { + return rf(ctx, fromBlock, eventSigs, addresses, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) int64); ok { + r0 = rf(ctx, fromBlock, eventSigs, addresses, confs) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) error); ok { + r1 = rf(ctx, fromBlock, eventSigs, addresses, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestBlockByEventSigsAddrsWithConfs' +type LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call struct { + *mock.Call +} + +// LatestBlockByEventSigsAddrsWithConfs is a helper method to define mock.On call +// - ctx context.Context +// - fromBlock int64 +// - eventSigs []common.Hash +// - addresses []common.Address +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LatestBlockByEventSigsAddrsWithConfs(ctx interface{}, fromBlock interface{}, eventSigs interface{}, addresses interface{}, confs interface{}) *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call { + return &LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call{Call: _e.mock.On("LatestBlockByEventSigsAddrsWithConfs", ctx, fromBlock, eventSigs, addresses, confs)} +} + +func (_c *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call) Run(run func(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations)) *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].([]common.Hash), args[3].([]common.Address), args[4].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call) Return(_a0 int64, _a1 error) *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call) RunAndReturn(run func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) (int64, error)) *LogPoller_LatestBlockByEventSigsAddrsWithConfs_Call { + _c.Call.Return(run) + return _c +} + +// LatestLogByEventSigWithConfs provides a mock function with given fields: ctx, eventSig, address, confs +func (_m *LogPoller) LatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs types.Confirmations) (*logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, confs) + + if len(ret) == 0 { + panic("no return value specified for LatestLogByEventSigWithConfs") + } + + var r0 *logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, types.Confirmations) (*logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, types.Confirmations) *logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LatestLogByEventSigWithConfs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestLogByEventSigWithConfs' +type LogPoller_LatestLogByEventSigWithConfs_Call struct { + *mock.Call +} + +// LatestLogByEventSigWithConfs is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LatestLogByEventSigWithConfs(ctx interface{}, eventSig interface{}, address interface{}, confs interface{}) *LogPoller_LatestLogByEventSigWithConfs_Call { + return &LogPoller_LatestLogByEventSigWithConfs_Call{Call: _e.mock.On("LatestLogByEventSigWithConfs", ctx, eventSig, address, confs)} +} + +func (_c *LogPoller_LatestLogByEventSigWithConfs_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, confs types.Confirmations)) *LogPoller_LatestLogByEventSigWithConfs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LatestLogByEventSigWithConfs_Call) Return(_a0 *logpoller.Log, _a1 error) *LogPoller_LatestLogByEventSigWithConfs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LatestLogByEventSigWithConfs_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, types.Confirmations) (*logpoller.Log, error)) *LogPoller_LatestLogByEventSigWithConfs_Call { + _c.Call.Return(run) + return _c +} + +// LatestLogEventSigsAddrsWithConfs provides a mock function with given fields: ctx, fromBlock, eventSigs, addresses, confs +func (_m *LogPoller) LatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, fromBlock, eventSigs, addresses, confs) + + if len(ret) == 0 { + panic("no return value specified for LatestLogEventSigsAddrsWithConfs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, fromBlock, eventSigs, addresses, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, fromBlock, eventSigs, addresses, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) error); ok { + r1 = rf(ctx, fromBlock, eventSigs, addresses, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LatestLogEventSigsAddrsWithConfs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LatestLogEventSigsAddrsWithConfs' +type LogPoller_LatestLogEventSigsAddrsWithConfs_Call struct { + *mock.Call +} + +// LatestLogEventSigsAddrsWithConfs is a helper method to define mock.On call +// - ctx context.Context +// - fromBlock int64 +// - eventSigs []common.Hash +// - addresses []common.Address +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LatestLogEventSigsAddrsWithConfs(ctx interface{}, fromBlock interface{}, eventSigs interface{}, addresses interface{}, confs interface{}) *LogPoller_LatestLogEventSigsAddrsWithConfs_Call { + return &LogPoller_LatestLogEventSigsAddrsWithConfs_Call{Call: _e.mock.On("LatestLogEventSigsAddrsWithConfs", ctx, fromBlock, eventSigs, addresses, confs)} +} + +func (_c *LogPoller_LatestLogEventSigsAddrsWithConfs_Call) Run(run func(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs types.Confirmations)) *LogPoller_LatestLogEventSigsAddrsWithConfs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].([]common.Hash), args[3].([]common.Address), args[4].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LatestLogEventSigsAddrsWithConfs_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LatestLogEventSigsAddrsWithConfs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LatestLogEventSigsAddrsWithConfs_Call) RunAndReturn(run func(context.Context, int64, []common.Hash, []common.Address, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_LatestLogEventSigsAddrsWithConfs_Call { + _c.Call.Return(run) + return _c +} + +// Logs provides a mock function with given fields: ctx, start, end, eventSig, address +func (_m *LogPoller) Logs(ctx context.Context, start int64, end int64, eventSig common.Hash, address common.Address) ([]logpoller.Log, error) { + ret := _m.Called(ctx, start, end, eventSig, address) + + if len(ret) == 0 { + panic("no return value specified for Logs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, common.Hash, common.Address) ([]logpoller.Log, error)); ok { + return rf(ctx, start, end, eventSig, address) + } + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, common.Hash, common.Address) []logpoller.Log); ok { + r0 = rf(ctx, start, end, eventSig, address) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, common.Hash, common.Address) error); ok { + r1 = rf(ctx, start, end, eventSig, address) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_Logs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Logs' +type LogPoller_Logs_Call struct { + *mock.Call +} + +// Logs is a helper method to define mock.On call +// - ctx context.Context +// - start int64 +// - end int64 +// - eventSig common.Hash +// - address common.Address +func (_e *LogPoller_Expecter) Logs(ctx interface{}, start interface{}, end interface{}, eventSig interface{}, address interface{}) *LogPoller_Logs_Call { + return &LogPoller_Logs_Call{Call: _e.mock.On("Logs", ctx, start, end, eventSig, address)} +} + +func (_c *LogPoller_Logs_Call) Run(run func(ctx context.Context, start int64, end int64, eventSig common.Hash, address common.Address)) *LogPoller_Logs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(common.Hash), args[4].(common.Address)) + }) + return _c +} + +func (_c *LogPoller_Logs_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_Logs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_Logs_Call) RunAndReturn(run func(context.Context, int64, int64, common.Hash, common.Address) ([]logpoller.Log, error)) *LogPoller_Logs_Call { + _c.Call.Return(run) + return _c +} + +// LogsCreatedAfter provides a mock function with given fields: ctx, eventSig, address, _a3, confs +func (_m *LogPoller) LogsCreatedAfter(ctx context.Context, eventSig common.Hash, address common.Address, _a3 time.Time, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, _a3, confs) + + if len(ret) == 0 { + panic("no return value specified for LogsCreatedAfter") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, _a3, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, _a3, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, _a3, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LogsCreatedAfter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LogsCreatedAfter' +type LogPoller_LogsCreatedAfter_Call struct { + *mock.Call +} + +// LogsCreatedAfter is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - _a3 time.Time +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LogsCreatedAfter(ctx interface{}, eventSig interface{}, address interface{}, _a3 interface{}, confs interface{}) *LogPoller_LogsCreatedAfter_Call { + return &LogPoller_LogsCreatedAfter_Call{Call: _e.mock.On("LogsCreatedAfter", ctx, eventSig, address, _a3, confs)} +} + +func (_c *LogPoller_LogsCreatedAfter_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, _a3 time.Time, confs types.Confirmations)) *LogPoller_LogsCreatedAfter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(time.Time), args[4].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LogsCreatedAfter_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LogsCreatedAfter_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LogsCreatedAfter_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, time.Time, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_LogsCreatedAfter_Call { + _c.Call.Return(run) + return _c +} + +// LogsDataWordBetween provides a mock function with given fields: ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs +func (_m *LogPoller) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) + + if len(ret) == 0 { + panic("no return value specified for LogsDataWordBetween") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LogsDataWordBetween_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LogsDataWordBetween' +type LogPoller_LogsDataWordBetween_Call struct { + *mock.Call +} + +// LogsDataWordBetween is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - wordIndexMin int +// - wordIndexMax int +// - wordValue common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LogsDataWordBetween(ctx interface{}, eventSig interface{}, address interface{}, wordIndexMin interface{}, wordIndexMax interface{}, wordValue interface{}, confs interface{}) *LogPoller_LogsDataWordBetween_Call { + return &LogPoller_LogsDataWordBetween_Call{Call: _e.mock.On("LogsDataWordBetween", ctx, eventSig, address, wordIndexMin, wordIndexMax, wordValue, confs)} +} + +func (_c *LogPoller_LogsDataWordBetween_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs types.Confirmations)) *LogPoller_LogsDataWordBetween_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].(int), args[5].(common.Hash), args[6].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LogsDataWordBetween_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LogsDataWordBetween_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LogsDataWordBetween_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_LogsDataWordBetween_Call { + _c.Call.Return(run) + return _c +} + +// LogsDataWordGreaterThan provides a mock function with given fields: ctx, eventSig, address, wordIndex, wordValueMin, confs +func (_m *LogPoller) LogsDataWordGreaterThan(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, wordIndex, wordValueMin, confs) + + if len(ret) == 0 { + panic("no return value specified for LogsDataWordGreaterThan") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, wordIndex, wordValueMin, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LogsDataWordGreaterThan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LogsDataWordGreaterThan' +type LogPoller_LogsDataWordGreaterThan_Call struct { + *mock.Call +} + +// LogsDataWordGreaterThan is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - wordIndex int +// - wordValueMin common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LogsDataWordGreaterThan(ctx interface{}, eventSig interface{}, address interface{}, wordIndex interface{}, wordValueMin interface{}, confs interface{}) *LogPoller_LogsDataWordGreaterThan_Call { + return &LogPoller_LogsDataWordGreaterThan_Call{Call: _e.mock.On("LogsDataWordGreaterThan", ctx, eventSig, address, wordIndex, wordValueMin, confs)} +} + +func (_c *LogPoller_LogsDataWordGreaterThan_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, confs types.Confirmations)) *LogPoller_LogsDataWordGreaterThan_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].(common.Hash), args[5].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LogsDataWordGreaterThan_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LogsDataWordGreaterThan_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LogsDataWordGreaterThan_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_LogsDataWordGreaterThan_Call { + _c.Call.Return(run) + return _c +} + +// LogsDataWordRange provides a mock function with given fields: ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs +func (_m *LogPoller) LogsDataWordRange(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, wordValueMax common.Hash, confs types.Confirmations) ([]logpoller.Log, error) { + ret := _m.Called(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) + + if len(ret) == 0 { + panic("no return value specified for LogsDataWordRange") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)); ok { + return rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) []logpoller.Log); ok { + r0 = rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) error); ok { + r1 = rf(ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LogsDataWordRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LogsDataWordRange' +type LogPoller_LogsDataWordRange_Call struct { + *mock.Call +} + +// LogsDataWordRange is a helper method to define mock.On call +// - ctx context.Context +// - eventSig common.Hash +// - address common.Address +// - wordIndex int +// - wordValueMin common.Hash +// - wordValueMax common.Hash +// - confs types.Confirmations +func (_e *LogPoller_Expecter) LogsDataWordRange(ctx interface{}, eventSig interface{}, address interface{}, wordIndex interface{}, wordValueMin interface{}, wordValueMax interface{}, confs interface{}) *LogPoller_LogsDataWordRange_Call { + return &LogPoller_LogsDataWordRange_Call{Call: _e.mock.On("LogsDataWordRange", ctx, eventSig, address, wordIndex, wordValueMin, wordValueMax, confs)} +} + +func (_c *LogPoller_LogsDataWordRange_Call) Run(run func(ctx context.Context, eventSig common.Hash, address common.Address, wordIndex int, wordValueMin common.Hash, wordValueMax common.Hash, confs types.Confirmations)) *LogPoller_LogsDataWordRange_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash), args[2].(common.Address), args[3].(int), args[4].(common.Hash), args[5].(common.Hash), args[6].(types.Confirmations)) + }) + return _c +} + +func (_c *LogPoller_LogsDataWordRange_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LogsDataWordRange_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LogsDataWordRange_Call) RunAndReturn(run func(context.Context, common.Hash, common.Address, int, common.Hash, common.Hash, types.Confirmations) ([]logpoller.Log, error)) *LogPoller_LogsDataWordRange_Call { + _c.Call.Return(run) + return _c +} + +// LogsWithSigs provides a mock function with given fields: ctx, start, end, eventSigs, address +func (_m *LogPoller) LogsWithSigs(ctx context.Context, start int64, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { + ret := _m.Called(ctx, start, end, eventSigs, address) + + if len(ret) == 0 { + panic("no return value specified for LogsWithSigs") + } + + var r0 []logpoller.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, []common.Hash, common.Address) ([]logpoller.Log, error)); ok { + return rf(ctx, start, end, eventSigs, address) + } + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, []common.Hash, common.Address) []logpoller.Log); ok { + r0 = rf(ctx, start, end, eventSigs, address) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]logpoller.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, []common.Hash, common.Address) error); ok { + r1 = rf(ctx, start, end, eventSigs, address) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LogPoller_LogsWithSigs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LogsWithSigs' +type LogPoller_LogsWithSigs_Call struct { + *mock.Call +} + +// LogsWithSigs is a helper method to define mock.On call +// - ctx context.Context +// - start int64 +// - end int64 +// - eventSigs []common.Hash +// - address common.Address +func (_e *LogPoller_Expecter) LogsWithSigs(ctx interface{}, start interface{}, end interface{}, eventSigs interface{}, address interface{}) *LogPoller_LogsWithSigs_Call { + return &LogPoller_LogsWithSigs_Call{Call: _e.mock.On("LogsWithSigs", ctx, start, end, eventSigs, address)} +} + +func (_c *LogPoller_LogsWithSigs_Call) Run(run func(ctx context.Context, start int64, end int64, eventSigs []common.Hash, address common.Address)) *LogPoller_LogsWithSigs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].([]common.Hash), args[4].(common.Address)) + }) + return _c +} + +func (_c *LogPoller_LogsWithSigs_Call) Return(_a0 []logpoller.Log, _a1 error) *LogPoller_LogsWithSigs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *LogPoller_LogsWithSigs_Call) RunAndReturn(run func(context.Context, int64, int64, []common.Hash, common.Address) ([]logpoller.Log, error)) *LogPoller_LogsWithSigs_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with no fields +func (_m *LogPoller) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// LogPoller_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type LogPoller_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *LogPoller_Expecter) Name() *LogPoller_Name_Call { + return &LogPoller_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *LogPoller_Name_Call) Run(run func()) *LogPoller_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_Name_Call) Return(_a0 string) *LogPoller_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Name_Call) RunAndReturn(run func() string) *LogPoller_Name_Call { + _c.Call.Return(run) + return _c +} + +// Ready provides a mock function with no fields +func (_m *LogPoller) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type LogPoller_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *LogPoller_Expecter) Ready() *LogPoller_Ready_Call { + return &LogPoller_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *LogPoller_Ready_Call) Run(run func()) *LogPoller_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *LogPoller_Ready_Call) Return(_a0 error) *LogPoller_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Ready_Call) RunAndReturn(run func() error) *LogPoller_Ready_Call { + _c.Call.Return(run) + return _c +} + +// RegisterFilter provides a mock function with given fields: ctx, filter +func (_m *LogPoller) RegisterFilter(ctx context.Context, filter logpoller.Filter) error { + ret := _m.Called(ctx, filter) + + if len(ret) == 0 { + panic("no return value specified for RegisterFilter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, logpoller.Filter) error); ok { + r0 = rf(ctx, filter) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_RegisterFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RegisterFilter' +type LogPoller_RegisterFilter_Call struct { + *mock.Call +} + +// RegisterFilter is a helper method to define mock.On call +// - ctx context.Context +// - filter logpoller.Filter +func (_e *LogPoller_Expecter) RegisterFilter(ctx interface{}, filter interface{}) *LogPoller_RegisterFilter_Call { + return &LogPoller_RegisterFilter_Call{Call: _e.mock.On("RegisterFilter", ctx, filter)} +} + +func (_c *LogPoller_RegisterFilter_Call) Run(run func(ctx context.Context, filter logpoller.Filter)) *LogPoller_RegisterFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(logpoller.Filter)) + }) + return _c +} + +func (_c *LogPoller_RegisterFilter_Call) Return(_a0 error) *LogPoller_RegisterFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_RegisterFilter_Call) RunAndReturn(run func(context.Context, logpoller.Filter) error) *LogPoller_RegisterFilter_Call { + _c.Call.Return(run) + return _c +} + +// Replay provides a mock function with given fields: ctx, fromBlock +func (_m *LogPoller) Replay(ctx context.Context, fromBlock int64) error { + ret := _m.Called(ctx, fromBlock) + + if len(ret) == 0 { + panic("no return value specified for Replay") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, fromBlock) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_Replay_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Replay' +type LogPoller_Replay_Call struct { + *mock.Call +} + +// Replay is a helper method to define mock.On call +// - ctx context.Context +// - fromBlock int64 +func (_e *LogPoller_Expecter) Replay(ctx interface{}, fromBlock interface{}) *LogPoller_Replay_Call { + return &LogPoller_Replay_Call{Call: _e.mock.On("Replay", ctx, fromBlock)} +} + +func (_c *LogPoller_Replay_Call) Run(run func(ctx context.Context, fromBlock int64)) *LogPoller_Replay_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64)) + }) + return _c +} + +func (_c *LogPoller_Replay_Call) Return(_a0 error) *LogPoller_Replay_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Replay_Call) RunAndReturn(run func(context.Context, int64) error) *LogPoller_Replay_Call { + _c.Call.Return(run) + return _c +} + +// ReplayAsync provides a mock function with given fields: fromBlock +func (_m *LogPoller) ReplayAsync(fromBlock int64) { + _m.Called(fromBlock) +} + +// LogPoller_ReplayAsync_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReplayAsync' +type LogPoller_ReplayAsync_Call struct { + *mock.Call +} + +// ReplayAsync is a helper method to define mock.On call +// - fromBlock int64 +func (_e *LogPoller_Expecter) ReplayAsync(fromBlock interface{}) *LogPoller_ReplayAsync_Call { + return &LogPoller_ReplayAsync_Call{Call: _e.mock.On("ReplayAsync", fromBlock)} +} + +func (_c *LogPoller_ReplayAsync_Call) Run(run func(fromBlock int64)) *LogPoller_ReplayAsync_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int64)) + }) + return _c +} + +func (_c *LogPoller_ReplayAsync_Call) Return() *LogPoller_ReplayAsync_Call { + _c.Call.Return() + return _c +} + +func (_c *LogPoller_ReplayAsync_Call) RunAndReturn(run func(int64)) *LogPoller_ReplayAsync_Call { + _c.Run(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *LogPoller) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type LogPoller_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *LogPoller_Expecter) Start(_a0 interface{}) *LogPoller_Start_Call { + return &LogPoller_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *LogPoller_Start_Call) Run(run func(_a0 context.Context)) *LogPoller_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *LogPoller_Start_Call) Return(_a0 error) *LogPoller_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_Start_Call) RunAndReturn(run func(context.Context) error) *LogPoller_Start_Call { + _c.Call.Return(run) + return _c +} + +// UnregisterFilter provides a mock function with given fields: ctx, name +func (_m *LogPoller) UnregisterFilter(ctx context.Context, name string) error { + ret := _m.Called(ctx, name) + + if len(ret) == 0 { + panic("no return value specified for UnregisterFilter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, name) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// LogPoller_UnregisterFilter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnregisterFilter' +type LogPoller_UnregisterFilter_Call struct { + *mock.Call +} + +// UnregisterFilter is a helper method to define mock.On call +// - ctx context.Context +// - name string +func (_e *LogPoller_Expecter) UnregisterFilter(ctx interface{}, name interface{}) *LogPoller_UnregisterFilter_Call { + return &LogPoller_UnregisterFilter_Call{Call: _e.mock.On("UnregisterFilter", ctx, name)} +} + +func (_c *LogPoller_UnregisterFilter_Call) Run(run func(ctx context.Context, name string)) *LogPoller_UnregisterFilter_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *LogPoller_UnregisterFilter_Call) Return(_a0 error) *LogPoller_UnregisterFilter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *LogPoller_UnregisterFilter_Call) RunAndReturn(run func(context.Context, string) error) *LogPoller_UnregisterFilter_Call { + _c.Call.Return(run) + return _c +} + +// NewLogPoller creates a new instance of LogPoller. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLogPoller(t interface { + mock.TestingT + Cleanup(func()) +}) *LogPoller { + mock := &LogPoller{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/transmitter/contract_transmitter.go b/pkg/transmitter/contract_transmitter.go new file mode 100644 index 0000000000..33cdc929a3 --- /dev/null +++ b/pkg/transmitter/contract_transmitter.go @@ -0,0 +1,271 @@ +package transmitter + +import ( + "context" + "database/sql" + "encoding/hex" + "math/big" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + evmkeystore "github.com/smartcontractkit/chainlink-evm/pkg/keys" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + "github.com/smartcontractkit/chainlink-evm/pkg/txmgr" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" +) + +type ContractTransmitter interface { + services.Service + ocrtypes.ContractTransmitter +} + +var _ ContractTransmitter = &contractTransmitter{} + +type Transmitter interface { + CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, txMeta *txmgr.TxMeta) error + FromAddress(context.Context) gethcommon.Address + + // Dual transmission + CreateSecondaryEthTransaction(ctx context.Context, payload []byte, txMeta *txmgr.TxMeta) error + SecondaryFromAddress(context.Context) (gethcommon.Address, error) +} + +type ReportToEthMetadata func([]byte) (*txmgr.TxMeta, error) + +func reportToEvmTxMetaNoop([]byte) (*txmgr.TxMeta, error) { + return nil, nil +} + +type transmitterOps struct { + reportToEvmTxMeta ReportToEthMetadata + excludeSigs bool + retention time.Duration + maxLogsKept uint64 +} + +type OCRTransmitterOption func(transmitter *transmitterOps) + +func WithExcludeSignatures() OCRTransmitterOption { + return func(ct *transmitterOps) { + ct.excludeSigs = true + } +} + +func HasExcludeSignatures(opts []OCRTransmitterOption) bool { + transmitterOptions := &transmitterOps{} + for _, opt := range opts { + opt(transmitterOptions) + } + return transmitterOptions.excludeSigs +} + +func WithRetention(retention time.Duration) OCRTransmitterOption { + return func(ct *transmitterOps) { + ct.retention = retention + } +} + +func WithReportToEthMetadata(reportToEvmTxMeta ReportToEthMetadata) OCRTransmitterOption { + return func(ct *transmitterOps) { + if reportToEvmTxMeta != nil { + ct.reportToEvmTxMeta = reportToEvmTxMeta + } + } +} + +type contractTransmitter struct { + contractAddress gethcommon.Address + contractABI abi.ABI + transmitter Transmitter + transmittedEventSig common.Hash + contractReader contractReader + lp logpoller.LogPoller + lggr logger.Logger + ks evmkeystore.Locker + // Options + transmitterOptions *transmitterOps +} + +func transmitterFilterName(addr common.Address) string { + return logpoller.FilterName("OCR ContractTransmitter", addr.String()) +} + +func NewOCRContractTransmitter( + ctx context.Context, + address gethcommon.Address, + caller contractReader, + contractABI abi.ABI, + transmitter Transmitter, + lp logpoller.LogPoller, + lggr logger.Logger, + ks evmkeystore.Locker, + opts ...OCRTransmitterOption, +) (*contractTransmitter, error) { + transmitted, ok := contractABI.Events["Transmitted"] + if !ok { + return nil, errors.New("invalid ABI, missing transmitted") + } + + newContractTransmitter := &contractTransmitter{ + contractAddress: address, + contractABI: contractABI, + transmitter: transmitter, + transmittedEventSig: transmitted.ID, + lp: lp, + contractReader: caller, + lggr: logger.Named(lggr, "OCRContractTransmitter"), + ks: ks, + transmitterOptions: &transmitterOps{ + reportToEvmTxMeta: reportToEvmTxMetaNoop, + excludeSigs: false, + retention: 0, + maxLogsKept: 0, + }, + } + + for _, opt := range opts { + opt(newContractTransmitter.transmitterOptions) + } + + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: newContractTransmitter.transmitterOptions.retention, MaxLogsKept: newContractTransmitter.transmitterOptions.maxLogsKept}) + if err != nil { + return nil, err + } + return newContractTransmitter, nil +} + +// Transmit sends the report to the on-chain smart contract's Transmit method. +func (oc *contractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signatures []ocrtypes.AttributedOnchainSignature) error { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + if len(signatures) > 32 { + return errors.New("too many signatures, maximum is 32") + } + for i, as := range signatures { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + panic("eventTransmit(ev): error in SplitSignature") + } + if !oc.transmitterOptions.excludeSigs { + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } + } + rawReportCtx := evmutil.RawReportContext(reportCtx) + + txMeta, err := oc.transmitterOptions.reportToEvmTxMeta(report) + if err != nil { + oc.lggr.Warnw("failed to generate tx metadata for report", "err", err) + } + + oc.lggr.Debugw("Transmitting report", "report", hex.EncodeToString(report), "rawReportCtx", rawReportCtx, "contractAddress", oc.contractAddress, "txMeta", txMeta) + + payload, err := oc.contractABI.Pack("transmit", rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return errors.Wrap(err, "abi.Pack failed") + } + + return errors.Wrap(oc.transmitter.CreateEthTransaction(ctx, oc.contractAddress, payload, txMeta), "failed to send Eth transaction") +} + +type contractReader interface { + CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) +} + +func parseTransmitted(log []byte) ([32]byte, uint32, error) { + var args abi.Arguments = []abi.Argument{ + { + Name: "configDigest", + Type: utils.MustAbiType("bytes32", nil), + }, + { + Name: "epoch", + Type: utils.MustAbiType("uint32", nil), + }, + } + transmitted, err := args.Unpack(log) + if err != nil { + return [32]byte{}, 0, err + } + if len(transmitted) < 2 { + return [32]byte{}, 0, errors.New("transmitted event log has too few arguments") + } + configDigest := *abi.ConvertType(transmitted[0], new([32]byte)).(*[32]byte) + epoch := *abi.ConvertType(transmitted[1], new(uint32)).(*uint32) + return configDigest, epoch, err +} + +func callContract(ctx context.Context, addr common.Address, contractABI abi.ABI, method string, args []interface{}, caller contractReader) ([]interface{}, error) { + input, err := contractABI.Pack(method, args...) + if err != nil { + return nil, err + } + output, err := caller.CallContract(ctx, ethereum.CallMsg{To: &addr, Data: input}, nil) + if err != nil { + return nil, err + } + return contractABI.Unpack(method, output) +} + +// LatestConfigDigestAndEpoch retrieves the latest config digest and epoch from the OCR2 contract. +// It is plugin independent, in particular avoids use of the plugin specific generated evm wrappers +// by using the evm client Call directly for functions/events that are part of OCR2Abstract. +func (oc *contractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) (ocrtypes.ConfigDigest, uint32, error) { + latestConfigDigestAndEpoch, err := callContract(ctx, oc.contractAddress, oc.contractABI, "latestConfigDigestAndEpoch", nil, oc.contractReader) + if err != nil { + return ocrtypes.ConfigDigest{}, 0, err + } + // Panic on these conversions erroring, would mean a broken contract. + scanLogs := *abi.ConvertType(latestConfigDigestAndEpoch[0], new(bool)).(*bool) + configDigest := *abi.ConvertType(latestConfigDigestAndEpoch[1], new([32]byte)).(*[32]byte) + epoch := *abi.ConvertType(latestConfigDigestAndEpoch[2], new(uint32)).(*uint32) + if !scanLogs { + return configDigest, epoch, nil + } + + // Otherwise, we have to scan for the logs. + latest, err := oc.lp.LatestLogByEventSigWithConfs(ctx, oc.transmittedEventSig, oc.contractAddress, 1) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + // No transmissions yet + return configDigest, 0, nil + } + return ocrtypes.ConfigDigest{}, 0, err + } + return parseTransmitted(latest.Data) +} + +// FromAccount returns the account from which the transmitter invokes the contract +func (oc *contractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return ocrtypes.Account(oc.transmitter.FromAddress(ctx).String()), nil +} + +func (oc *contractTransmitter) Start(ctx context.Context) error { + // Lock the transmitters to TXMv1 + rm := oc.ks.GetMutex(oc.transmitter.FromAddress(ctx)) + return rm.TryLock(evmkeystore.TXMv1) +} +func (oc *contractTransmitter) Close() error { + // Unlock the transmitters to TXMv1 + rm := oc.ks.GetMutex(oc.transmitter.FromAddress(context.Background())) + return rm.Unlock(evmkeystore.TXMv1) +} + +// Has no state/lifecycle so it's always healthy and ready +func (oc *contractTransmitter) Ready() error { return nil } +func (oc *contractTransmitter) HealthReport() map[string]error { + return map[string]error{oc.Name(): nil} +} +func (oc *contractTransmitter) Name() string { return oc.lggr.Name() } diff --git a/pkg/transmitter/contract_transmitter_test.go b/pkg/transmitter/contract_transmitter_test.go new file mode 100644 index 0000000000..cc3d65111c --- /dev/null +++ b/pkg/transmitter/contract_transmitter_test.go @@ -0,0 +1,181 @@ +package transmitter + +import ( + "context" + "encoding/hex" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + libocr "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" + "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller/mocks" + "github.com/smartcontractkit/chainlink-evm/pkg/testutils" + "github.com/smartcontractkit/chainlink-evm/pkg/txmgr" +) + +var sampleAddress = testutils.NewAddress() + +type mockTransmitter struct { + lastPayload []byte +} + +func (m *mockTransmitter) SecondaryFromAddress(ctx context.Context) (gethcommon.Address, error) { + return gethcommon.Address{}, nil +} + +func (m *mockTransmitter) CreateSecondaryEthTransaction(ctx context.Context, bytes []byte, meta *txmgr.TxMeta) error { + return nil +} + +func (m *mockTransmitter) CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, _ *txmgr.TxMeta) error { + m.lastPayload = payload + return nil +} + +func (*mockTransmitter) FromAddress(ctx context.Context) gethcommon.Address { return sampleAddress } + +func TestContractTransmitter(t *testing.T) { + t.Parallel() + + lggr := logger.Test(t) + c := clienttest.NewClient(t) + lp := mocks.NewLogPoller(t) + ctx := testutils.Context(t) + // scanLogs = false + digestAndEpochDontScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000000" + // false + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochDontScanLogs, nil).Once() + contractABI, _ := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + reportToEvmTxMeta := func(b []byte) (*txmgr.TxMeta, error) { + return &txmgr.TxMeta{}, nil + } + ot, err := NewOCRContractTransmitter(ctx, gethcommon.Address{}, c, contractABI, &mockTransmitter{}, lp, lggr, &keystest.FakeChainStore{}, + WithReportToEthMetadata(reportToEvmTxMeta)) + require.NoError(t, err) + digest, epoch, err := ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + + // scanLogs = true + digestAndEpochScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000001" + // true + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochScanLogs, nil).Once() + transmitted2, _ := hex.DecodeString( + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + lp.On("LatestLogByEventSigWithConfs", + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&logpoller.Log{ + Data: transmitted2, + }, nil) + digest, epoch, err = ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + from, err := ot.FromAccount(t.Context()) + require.NoError(t, err) + assert.Equal(t, sampleAddress.String(), string(from)) +} + +func Test_contractTransmitterNoSignatures_Transmit_SignaturesAreNotTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createContractTransmitter(ctx, t, transmitter, WithExcludeSignatures()) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + var emptyRs [][32]byte + var emptySs [][32]byte + var emptyVs [32]byte + emptySignaturesPayload, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), emptyRs, emptySs, emptyVs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPayload, emptySignaturesPayload) +} + +func Test_contractTransmitter_Transmit_SignaturesAreTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createContractTransmitter(ctx, t, transmitter) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + rs, ss, vs := signaturesAsPayload(t, signatures) + withSignaturesPayload, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), rs, ss, vs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPayload, withSignaturesPayload) +} + +func signaturesAsPayload(t *testing.T, signatures []ocrtypes.AttributedOnchainSignature) ([][32]byte, [][32]byte, [32]byte) { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + r, s, v, err := evmutil.SplitSignature(signatures[0].Signature) + require.NoError(t, err) + rs = append(rs, r) + ss = append(ss, s) + vs[0] = v + return rs, ss, vs +} + +func oneSignature() []ocrtypes.AttributedOnchainSignature { + signaturesData := make([]byte, 65) + signaturesData[9] = 8 + signaturesData[7] = 6 + return []libocr.AttributedOnchainSignature{{Signature: signaturesData, Signer: commontypes.OracleID(54)}} +} + +func createContractTransmitter(ctx context.Context, t *testing.T, transmitter Transmitter, ops ...OCRTransmitterOption) *contractTransmitter { + contractABI, err := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + require.NoError(t, err) + lp := mocks.NewLogPoller(t) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + contractTransmitter, err := NewOCRContractTransmitter( + ctx, + gethcommon.Address{}, + clienttest.NewClient(t), + contractABI, + transmitter, + lp, + logger.Test(t), + &keystest.FakeChainStore{}, + ops..., + ) + require.NoError(t, err) + return contractTransmitter +} diff --git a/pkg/transmitter/dual_contract_transmitter.go b/pkg/transmitter/dual_contract_transmitter.go new file mode 100644 index 0000000000..4084a61290 --- /dev/null +++ b/pkg/transmitter/dual_contract_transmitter.go @@ -0,0 +1,257 @@ +package transmitter + +import ( + "context" + "database/sql" + "encoding/hex" + stderrors "errors" + "fmt" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/accounts/abi" + + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-evm/pkg/keys" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" +) + +// TODO: Remove when new dual transmitter contracts are merged +var dtABI = `[{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"report","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmitSecondary","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + +var _ ContractTransmitter = (*dualContractTransmitter)(nil) + +type dualContractTransmitter struct { + contractAddress gethcommon.Address + contractABI abi.ABI + dualTransmissionABI abi.ABI + transmitter Transmitter + transmittedEventSig gethcommon.Hash + contractReader contractReader + lp logpoller.LogPoller + lggr logger.Logger + ks keys.Locker + // Options + transmitterOptions *transmitterOps +} + +var dualTransmissionABI = sync.OnceValue(func() abi.ABI { + dualTransmissionABI, err := abi.JSON(strings.NewReader(dtABI)) + if err != nil { + panic(fmt.Errorf("failed to parse dualTransmission ABI: %w", err)) + } + return dualTransmissionABI +}) + +func NewOCRDualContractTransmitter( + ctx context.Context, + address gethcommon.Address, + caller contractReader, + contractABI abi.ABI, + transmitter Transmitter, + lp logpoller.LogPoller, + lggr logger.Logger, + ethKeystore keys.Locker, + opts ...OCRTransmitterOption, +) (*dualContractTransmitter, error) { + transmitted, ok := contractABI.Events["Transmitted"] + if !ok { + return nil, errors.New("invalid ABI, missing transmitted") + } + + newContractTransmitter := &dualContractTransmitter{ + contractAddress: address, + contractABI: contractABI, + dualTransmissionABI: dualTransmissionABI(), + transmitter: transmitter, + transmittedEventSig: transmitted.ID, + lp: lp, + contractReader: caller, + lggr: logger.Named(lggr, "OCR2DualContractTransmitter"), + ks: ethKeystore, + transmitterOptions: &transmitterOps{ + reportToEvmTxMeta: reportToEvmTxMetaNoop, + excludeSigs: false, + retention: 0, + maxLogsKept: 0, + }, + } + + for _, opt := range opts { + opt(newContractTransmitter.transmitterOptions) + } + + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []gethcommon.Hash{transmitted.ID}, Addresses: []gethcommon.Address{address}, Retention: newContractTransmitter.transmitterOptions.retention, MaxLogsKept: newContractTransmitter.transmitterOptions.maxLogsKept}) + if err != nil { + return nil, err + } + return newContractTransmitter, nil +} + +// Transmit sends the report to the on-chain smart contract's Transmit method. +func (oc *dualContractTransmitter) Transmit(ctx context.Context, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signatures []ocrtypes.AttributedOnchainSignature) error { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + if len(signatures) > 32 { + return errors.New("too many signatures, maximum is 32") + } + for i, as := range signatures { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + panic("eventTransmit(ev): error in SplitSignature") + } + if !oc.transmitterOptions.excludeSigs { + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } + } + rawReportCtx := evmutil.RawReportContext(reportCtx) + + txMeta, err := oc.transmitterOptions.reportToEvmTxMeta(report) + if err != nil { + oc.lggr.Warnw("failed to generate tx metadata for report", "err", err) + } + + oc.lggr.Debugw("Transmitting report", "report", hex.EncodeToString(report), "rawReportCtx", rawReportCtx, "contractAddress", oc.contractAddress, "txMeta", txMeta) + + // Primary transmission + payload, err := oc.contractABI.Pack("transmit", rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return errors.Wrap(err, "abi.Pack failed") + } + + transactionErr := errors.Wrap(oc.transmitter.CreateEthTransaction(ctx, oc.contractAddress, payload, txMeta), "failed to send primary Eth transaction") + + oc.lggr.Debugw("Created primary transaction", "error", transactionErr) + + // Secondary transmission + secondaryPayload, err := oc.dualTransmissionABI.Pack("transmitSecondary", rawReportCtx, []byte(report), rs, ss, vs) + if err != nil { + return errors.Wrap(err, "transmitSecondary abi.Pack failed") + } + + err = errors.Wrap(oc.transmitter.CreateSecondaryEthTransaction(ctx, secondaryPayload, txMeta), "failed to send secondary Eth transaction") + oc.lggr.Debugw("Created secondary transaction", "error", err) + return stderrors.Join(transactionErr, err) +} + +// LatestConfigDigestAndEpoch retrieves the latest config digest and epoch from the OCR2 contract. +// It is plugin independent, in particular avoids use of the plugin specific generated evm wrappers +// by using the evm client Call directly for functions/events that are part of OCR2Abstract. +func (oc *dualContractTransmitter) LatestConfigDigestAndEpoch(ctx context.Context) (ocrtypes.ConfigDigest, uint32, error) { + latestConfigDigestAndEpoch, err := callContract(ctx, oc.contractAddress, oc.contractABI, "latestConfigDigestAndEpoch", nil, oc.contractReader) + if err != nil { + return ocrtypes.ConfigDigest{}, 0, err + } + // Panic on these conversions erroring, would mean a broken contract. + scanLogs := *abi.ConvertType(latestConfigDigestAndEpoch[0], new(bool)).(*bool) + configDigest := *abi.ConvertType(latestConfigDigestAndEpoch[1], new([32]byte)).(*[32]byte) + epoch := *abi.ConvertType(latestConfigDigestAndEpoch[2], new(uint32)).(*uint32) + if !scanLogs { + return configDigest, epoch, nil + } + + // Otherwise, we have to scan for the logs. + latest, err := oc.lp.LatestLogByEventSigWithConfs(ctx, oc.transmittedEventSig, oc.contractAddress, 1) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + // No transmissions yet + return configDigest, 0, nil + } + return ocrtypes.ConfigDigest{}, 0, err + } + return parseTransmitted(latest.Data) +} + +// FromAccount returns the account from which the transmitter invokes the contract +func (oc *dualContractTransmitter) FromAccount(ctx context.Context) (ocrtypes.Account, error) { + return ocrtypes.Account(oc.transmitter.FromAddress(ctx).String()), nil +} + +func (oc *dualContractTransmitter) lockTransmitters(ctx context.Context) error { + err := oc.lockPrimary(ctx) + if err != nil { + return err + } + err = oc.lockSecondary(ctx) + if err != nil { + return stderrors.Join(err, oc.unlockPrimary(ctx)) + } + return nil +} + +func (oc *dualContractTransmitter) unlockTransmitters(ctx context.Context) error { + return stderrors.Join(oc.unlockPrimary(ctx), oc.unlockSecondary(ctx)) +} + +func (oc *dualContractTransmitter) unlockPrimary(ctx context.Context) error { + primaryAddress := oc.transmitter.FromAddress(ctx) + rmPrimary := oc.ks.GetMutex(primaryAddress) + err := rmPrimary.Unlock(keys.TXMv1) + if err != nil { + return err + } + oc.lggr.Debugf("Key %s has been unlocked for TXMv1", primaryAddress.String()) + return nil +} + +func (oc *dualContractTransmitter) unlockSecondary(ctx context.Context) error { + secondaryAddress, err := oc.transmitter.SecondaryFromAddress(ctx) + if err != nil { + return err + } + rmSecondary := oc.ks.GetMutex(secondaryAddress) + err = rmSecondary.Unlock(keys.TXMv2) + if err != nil { + return err + } + oc.lggr.Debugf("Key %s has been unlocked for TXMv2", secondaryAddress.String()) + return nil +} + +func (oc *dualContractTransmitter) lockPrimary(ctx context.Context) error { + primaryAddress := oc.transmitter.FromAddress(ctx) + rmPrimary := oc.ks.GetMutex(primaryAddress) + err := rmPrimary.TryLock(keys.TXMv1) + if err != nil { + return err + } + oc.lggr.Debugf("Key %s has been locked for TXMv1", primaryAddress.String()) + return nil +} + +func (oc *dualContractTransmitter) lockSecondary(ctx context.Context) error { + secondaryAddress, err := oc.transmitter.SecondaryFromAddress(ctx) + if err != nil { + return err + } + rmSecondary := oc.ks.GetMutex(secondaryAddress) + err = rmSecondary.TryLock(keys.TXMv2) + if err != nil { + return err + } + oc.lggr.Debugf("Key %s has been locked for TXMv2", secondaryAddress.String()) + return nil +} + +func (oc *dualContractTransmitter) Start(ctx context.Context) error { + return oc.lockTransmitters(ctx) +} +func (oc *dualContractTransmitter) Close() error { + return oc.unlockTransmitters(context.Background()) +} + +// Has no state/lifecycle so it's always healthy and ready +func (oc *dualContractTransmitter) Ready() error { return nil } +func (oc *dualContractTransmitter) HealthReport() map[string]error { + return map[string]error{oc.Name(): nil} +} +func (oc *dualContractTransmitter) Name() string { return oc.lggr.Name() } diff --git a/pkg/transmitter/dual_contract_transmitter_test.go b/pkg/transmitter/dual_contract_transmitter_test.go new file mode 100644 index 0000000000..0743485197 --- /dev/null +++ b/pkg/transmitter/dual_contract_transmitter_test.go @@ -0,0 +1,168 @@ +package transmitter + +import ( + "context" + "encoding/hex" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" + "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + "github.com/smartcontractkit/chainlink-evm/pkg/logpoller/mocks" + "github.com/smartcontractkit/chainlink-evm/pkg/testutils" + "github.com/smartcontractkit/chainlink-evm/pkg/txmgr" +) + +var sampleAddressPrimary = testutils.NewAddress() + +type mockDualTransmitter struct { + lastPrimaryPayload []byte + lastSecondaryPayload []byte +} + +func (m *mockDualTransmitter) SecondaryFromAddress(ctx context.Context) (gethcommon.Address, error) { + return gethcommon.Address{}, nil +} + +func (*mockDualTransmitter) FromAddress(ctx context.Context) gethcommon.Address { + return sampleAddressPrimary +} + +func (m *mockDualTransmitter) CreateEthTransaction(ctx context.Context, toAddress gethcommon.Address, payload []byte, _ *txmgr.TxMeta) error { + m.lastPrimaryPayload = payload + return nil +} + +func (m *mockDualTransmitter) CreateSecondaryEthTransaction(ctx context.Context, payload []byte, _ *txmgr.TxMeta) error { + m.lastSecondaryPayload = payload + return nil +} + +func TestDualContractTransmitter(t *testing.T) { + t.Parallel() + + lggr := logger.Test(t) + c := clienttest.NewClient(t) + lp := mocks.NewLogPoller(t) + ctx := testutils.Context(t) + // scanLogs = false + digestAndEpochDontScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000000" + // false + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochDontScanLogs, nil).Once() + contractABI, _ := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + reportToEvmTxMeta := func(b []byte) (*txmgr.TxMeta, error) { + return &txmgr.TxMeta{}, nil + } + ot, err := NewOCRDualContractTransmitter(ctx, gethcommon.Address{}, c, contractABI, &mockDualTransmitter{}, lp, lggr, &keystest.FakeChainStore{}, WithReportToEthMetadata(reportToEvmTxMeta)) + require.NoError(t, err) + digest, epoch, err := ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + + // scanLogs = true + digestAndEpochScanLogs, _ := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000001" + // true + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(digestAndEpochScanLogs, nil).Once() + transmitted2, _ := hex.DecodeString( + "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777" + // config digest + "0000000000000000000000000000000000000000000000000000000000000002") // epoch + lp.On("LatestLogByEventSigWithConfs", + mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&logpoller.Log{ + Data: transmitted2, + }, nil) + digest, epoch, err = ot.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc777", hex.EncodeToString(digest[:])) + assert.Equal(t, uint32(2), epoch) + from, err := ot.FromAccount(t.Context()) + require.NoError(t, err) + assert.Equal(t, sampleAddressPrimary.String(), string(from)) +} + +func Test_dualContractTransmitterNoSignatures_Transmit_SignaturesAreNotTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockDualTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createDualContractTransmitter(ctx, t, transmitter, WithExcludeSignatures()) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + var emptyRs [][32]byte + var emptySs [][32]byte + var emptyVs [32]byte + emptySignaturesPayloadPrimary, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), emptyRs, emptySs, emptyVs) + require.NoError(t, err) + emptySignaturesPayloadSecondary, err := oc.dualTransmissionABI.Pack("transmitSecondary", evmutil.RawReportContext(reportCtx), []byte(report), emptyRs, emptySs, emptyVs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPrimaryPayload, emptySignaturesPayloadPrimary, "primary payload not equal") + require.Equal(t, transmitter.lastSecondaryPayload, emptySignaturesPayloadSecondary, "secondary payload not equal") +} + +func Test_dualContractTransmitter_Transmit_SignaturesAreTransmitted(t *testing.T) { + t.Parallel() + + transmitter := &mockDualTransmitter{} + + ctx := context.Background() + reportCtx := types.ReportContext{} + report := types.Report{} + var signatures = oneSignature() + + oc := createDualContractTransmitter(ctx, t, transmitter) + + err := oc.Transmit(ctx, reportCtx, report, signatures) + require.NoError(t, err) + + rs, ss, vs := signaturesAsPayload(t, signatures) + withSignaturesPayloadPrimary, err := oc.contractABI.Pack("transmit", evmutil.RawReportContext(reportCtx), []byte(report), rs, ss, vs) + require.NoError(t, err) + withSignaturesPayloadSecondary, err := oc.dualTransmissionABI.Pack("transmitSecondary", evmutil.RawReportContext(reportCtx), []byte(report), rs, ss, vs) + require.NoError(t, err) + require.Equal(t, transmitter.lastPrimaryPayload, withSignaturesPayloadPrimary, "primary payload not equal") + require.Equal(t, transmitter.lastSecondaryPayload, withSignaturesPayloadSecondary, "secondary payload not equal") +} + +func createDualContractTransmitter(ctx context.Context, t *testing.T, transmitter Transmitter, ops ...OCRTransmitterOption) *dualContractTransmitter { + contractABI, err := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorMetaData.ABI)) + require.NoError(t, err) + lp := mocks.NewLogPoller(t) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) + contractTransmitter, err := NewOCRDualContractTransmitter( + ctx, + gethcommon.Address{}, + clienttest.NewClient(t), + contractABI, + transmitter, + lp, + logger.Test(t), + &keystest.FakeChainStore{}, + ops..., + ) + require.NoError(t, err) + return contractTransmitter +}