From 2a5449bb9a54d242e52d9fe46e1ae021e4d88451 Mon Sep 17 00:00:00 2001 From: minhthanh Date: Mon, 12 Aug 2024 11:01:38 +0700 Subject: [PATCH] add parser for uniswapx v1 (#63) * add parser for uniswapx v1 * add abi file * remove old log --- cmd/tradelogs/main.go | 2 + internal/worker/worker.go | 19 +- pkg/evmlistenerclient/client.go | 1 - pkg/parser/bebop/parser.go | 9 +- pkg/parser/hashflow_v3/parser.go | 4 +- pkg/parser/kyberswap/parser.go | 5 +- pkg/parser/kyberswap_rfq/parser.go | 4 +- pkg/parser/oneinchv6/parser.go | 8 +- pkg/parser/paraswap/parser.go | 4 +- pkg/parser/parser.go | 9 + pkg/parser/uniswapx/parser.go | 28 +- pkg/parser/uniswapx/uniswap_test.go | 4 +- pkg/parser/uniswapx_v1/abi.json | 1 + pkg/parser/uniswapx_v1/gen.sh | 1 + pkg/parser/uniswapx_v1/parser.go | 297 +++++++++ pkg/parser/uniswapx_v1/uniswap_test.go | 70 ++ pkg/parser/uniswapx_v1/uniswapx.go | 878 +++++++++++++++++++++++++ pkg/parser/zxotc/parser.go | 4 +- pkg/storage/storage.go | 13 + 19 files changed, 1316 insertions(+), 45 deletions(-) create mode 100644 pkg/parser/uniswapx_v1/abi.json create mode 100755 pkg/parser/uniswapx_v1/gen.sh create mode 100644 pkg/parser/uniswapx_v1/parser.go create mode 100644 pkg/parser/uniswapx_v1/uniswap_test.go create mode 100644 pkg/parser/uniswapx_v1/uniswapx.go diff --git a/cmd/tradelogs/main.go b/cmd/tradelogs/main.go index b589ec9..8c2c541 100644 --- a/cmd/tradelogs/main.go +++ b/cmd/tradelogs/main.go @@ -14,6 +14,7 @@ import ( "github.com/KyberNetwork/tradelogs/pkg/parser/bebop" "github.com/KyberNetwork/tradelogs/pkg/parser/oneinchv6" "github.com/KyberNetwork/tradelogs/pkg/parser/uniswapx" + uniswapxv1 "github.com/KyberNetwork/tradelogs/pkg/parser/uniswapx_v1" "github.com/KyberNetwork/tradelogs/pkg/parser/zxrfqv3" "github.com/KyberNetwork/tradelogs/pkg/pricefiller" "github.com/KyberNetwork/tradelogs/pkg/rpcnode" @@ -103,6 +104,7 @@ func run(c *cli.Context) error { kyberswaprfq.MustNewParser(), hashflowv3.MustNewParser(), oneinchv6.MustNewParser(traceCalls), + uniswapxv1.MustNewParser(traceCalls), uniswapx.MustNewParser(traceCalls), bebop.MustNewParser(traceCalls), zxrfqv3.MustNewParserWithDeployer(traceCalls, ethClient, common.HexToAddress(parser.Deployer0xV3)), diff --git a/internal/worker/worker.go b/internal/worker/worker.go index d63e776..e6fc75a 100644 --- a/internal/worker/worker.go +++ b/internal/worker/worker.go @@ -15,6 +15,11 @@ import ( "go.uber.org/zap" ) +const ( + RetryInterval = 4 * time.Second + RemoveInterval = time.Hour +) + type Worker struct { listener *evmlistenerclient.Client l *zap.SugaredLogger @@ -38,14 +43,19 @@ func New(l *zap.SugaredLogger, s *storage.Storage, listener *evmlistenerclient.C } func (w *Worker) Run(ctx context.Context) error { - retryTimer := time.NewTicker(evmlistenerclient.RetryTime) + retryTimer := time.NewTicker(RetryInterval) defer retryTimer.Stop() + removeTimer := time.NewTicker(RemoveInterval) + defer removeTimer.Stop() for { select { case <-retryTimer.C: if err := w.retryParseLog(); err != nil { w.l.Errorw("error when retry parse log", "err", err) - return err + } + case <-removeTimer.C: + if err := w.removeOldErrorLog(); err != nil { + w.l.Errorw("error when remove old error log", "err", err) } default: } @@ -184,3 +194,8 @@ func (w *Worker) findMatchingParser(log ethTypes.Log) parser.Parser { } return ps } + +func (w *Worker) removeOldErrorLog() error { + w.l.Info("start to remove old error log") + return w.s.RemoveLogUtil(time.Now().Add(-time.Hour * 24).Unix()) +} diff --git a/pkg/evmlistenerclient/client.go b/pkg/evmlistenerclient/client.go index 68f5402..b273100 100644 --- a/pkg/evmlistenerclient/client.go +++ b/pkg/evmlistenerclient/client.go @@ -17,7 +17,6 @@ const ( var ( BlockTime = 12 * time.Second - RetryTime = 2 * time.Second ) type Config struct { diff --git a/pkg/parser/bebop/parser.go b/pkg/parser/bebop/parser.go index a4772d9..d3f0b28 100644 --- a/pkg/parser/bebop/parser.go +++ b/pkg/parser/bebop/parser.go @@ -25,11 +25,6 @@ const ( OrderParam = "order" ) -var ( - ErrTradeTopic = errors.New("invalid trade topic") - ErrNotFoundLog = errors.New("not found log") -) - type SingleOrder struct { Expiry *big.Int `json:"expiry"` TakerAddress string `json:"taker_address"` @@ -146,7 +141,7 @@ func (p *Parser) searchTradeLog(order storage.TradeLog, traceCall types.CallFram } } traceData, _ := json.Marshal(traceCall) - return order, fmt.Errorf("%w %s", ErrNotFoundLog, string(traceData)) + return order, fmt.Errorf("%w %s", parser.ErrNotFoundTrade, string(traceData)) } func (p *Parser) checkBebopTrade(traceCall types.CallFrame, orderHash string) bool { @@ -253,7 +248,7 @@ func (p *Parser) UseTraceCall() bool { func (p *Parser) buildOrderByLog(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrTradeTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } o, err := p.ps.ParseBebopOrder(log) if err != nil { diff --git a/pkg/parser/hashflow_v3/parser.go b/pkg/parser/hashflow_v3/parser.go index 88708cf..764e7b1 100644 --- a/pkg/parser/hashflow_v3/parser.go +++ b/pkg/parser/hashflow_v3/parser.go @@ -21,8 +21,6 @@ const ( paramName = "quote" ) -var ErrTradeTopic = errors.New("invalid Trade topic") - type Parser struct { abi *abi.ABI ps *Hashflowv3Filterer @@ -57,7 +55,7 @@ func (p *Parser) Topics() []string { func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrTradeTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } o, err := p.ps.ParseTrade(log) if err != nil { diff --git a/pkg/parser/kyberswap/parser.go b/pkg/parser/kyberswap/parser.go index 53b51ea..b2ca417 100644 --- a/pkg/parser/kyberswap/parser.go +++ b/pkg/parser/kyberswap/parser.go @@ -1,7 +1,6 @@ package kyberswap import ( - "errors" "strings" tradingTypes "github.com/KyberNetwork/tradinglib/pkg/types" @@ -18,8 +17,6 @@ const ( SwappedEvent = "Swapped" ) -var ErrInvalidKSSwappedTopic = errors.New("invalid KS Swapped topic") - type Parser struct { abi *abi.ABI ps *SwappedFilterer @@ -54,7 +51,7 @@ func (p *Parser) Topics() []string { func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidKSSwappedTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } e, err := p.ps.ParseSwapped(log) if err != nil { diff --git a/pkg/parser/kyberswap_rfq/parser.go b/pkg/parser/kyberswap_rfq/parser.go index 59148fa..1532df6 100644 --- a/pkg/parser/kyberswap_rfq/parser.go +++ b/pkg/parser/kyberswap_rfq/parser.go @@ -23,8 +23,6 @@ const ( paramName = "order" ) -var ErrInvalidKSFilledTopic = errors.New("invalid KS order filled topic") - type Parser struct { abi *abi.ABI ps *KyberswaprfqFilterer @@ -59,7 +57,7 @@ func (p *Parser) Topics() []string { func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidKSFilledTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } e, err := p.ps.ParseOrderFilledRFQ(log) if err != nil { diff --git a/pkg/parser/oneinchv6/parser.go b/pkg/parser/oneinchv6/parser.go index 77cae7d..a1117cc 100644 --- a/pkg/parser/oneinchv6/parser.go +++ b/pkg/parser/oneinchv6/parser.go @@ -27,9 +27,7 @@ const ( ) var ( - ErrInvalidOneInchFilledTopic = errors.New("invalid oneinch order filled topic") - ErrNotFoundLog = errors.New("not found log") - RFQOrderOutputArgument abi.Arguments + RFQOrderOutputArgument abi.Arguments ) func init() { @@ -93,7 +91,7 @@ func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLo func (p *Parser) buildOrderByLog(log ethereumTypes.Log) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidOneInchFilledTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } e, err := p.ps.ParseOrderFilled(log) if err != nil { @@ -175,7 +173,7 @@ func (p *Parser) recursiveDetectOneInchRFQTrades(tradeLog storage.TradeLog, trac } traceData, _ := json.Marshal(traceCall) - return tradeLog, fmt.Errorf("%w %s", ErrNotFoundLog, string(traceData)) + return tradeLog, fmt.Errorf("%w %s", parser.ErrNotFoundTrade, string(traceData)) } func (p *Parser) isOneInchRFQTrades(txHash, orderHash string, traceCall types.CallFrame, count *int) bool { diff --git a/pkg/parser/paraswap/parser.go b/pkg/parser/paraswap/parser.go index 51ae152..ad19c2f 100644 --- a/pkg/parser/paraswap/parser.go +++ b/pkg/parser/paraswap/parser.go @@ -21,8 +21,6 @@ const ( paramName = "order" ) -var ErrInvalidRFQTopic = errors.New("invalid RfqFilled topic") - type Parser struct { abi *abi.ABI ps *OrderFilledFilterer @@ -57,7 +55,7 @@ func (p *Parser) Topics() []string { func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidRFQTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } o, err := p.ps.ParseOrderFilled(log) if err != nil { diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index ebbf788..d1032eb 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -1,6 +1,8 @@ package parser import ( + "errors" + "github.com/KyberNetwork/tradelogs/pkg/storage" tradingTypes "github.com/KyberNetwork/tradinglib/pkg/types" ethereumTypes "github.com/ethereum/go-ethereum/core/types" @@ -22,6 +24,7 @@ const ( ExUniswapX = "uniswapx" ExNative = "native" ExBebop = "bebop" + ExUniswapXV1 = "uniswapxV1" Addr1InchV6 = "0x111111125421cA6dc452d289314280a0f8842A65" AddrBebop = "0xbbbbbBB520d69a9775E85b458C58c648259FAD5F" @@ -30,10 +33,16 @@ const ( AddrKyberswapRFQ = "0x7A819Fa46734a49D0112796f9377E024c350FB26" AddrParaswap = "0xe92b586627ccA7a83dC919cc7127196d70f55a06" AddrUniswapX = "0x00000011F84B9aa48e5f8aA8B9897600006289Be" + AddrUniswapXV1 = "0x6000da47483062A0D734Ba3dc7576Ce6A0B645C4" Addr0x = "0xDef1C0ded9bec7F1a1670819833240f027b25EfF" Deployer0xV3 = "0x00000000000004533Fe15556B1E086BB1A72cEae" ) +var ( + ErrInvalidTopic = errors.New("invalid order topic") + ErrNotFoundTrade = errors.New("not found log") +) + type Parser interface { Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) Topics() []string diff --git a/pkg/parser/uniswapx/parser.go b/pkg/parser/uniswapx/parser.go index dba3109..10962e3 100644 --- a/pkg/parser/uniswapx/parser.go +++ b/pkg/parser/uniswapx/parser.go @@ -20,8 +20,7 @@ import ( ) const ( - FilledEvent = "Fill" - TransferEvent = "Transfer" + FilledEvent = "Fill" ) type ResolvedOrder struct { @@ -58,11 +57,6 @@ type ResolvedOrder struct { Cosignature []uint8 "json:\"cosignature\"" } -var ( - ErrInvalidOneInchFilledTopic = errors.New("invalid uniswapx order filled topic") - ErrNotFoundLog = errors.New("not found log") -) - type Parser struct { abi *abi.ABI ps *UniswapxFilterer @@ -151,7 +145,7 @@ func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLo func (p *Parser) buildOrderByLog(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidOneInchFilledTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } e, err := p.ps.ParseFill(log) if err != nil { @@ -232,7 +226,7 @@ func (p *Parser) recursiveDetectRFQTrades(order storage.TradeLog, call types.Cal } } traceData, _ := json.Marshal(call) - return order, fmt.Errorf("%w %s", ErrNotFoundLog, string(traceData)) + return order, fmt.Errorf("%w %s", parser.ErrNotFoundTrade, string(traceData)) } func (p *Parser) updateOrder(internal storage.TradeLog, parsed []interface{}) (storage.TradeLog, error) { @@ -280,7 +274,9 @@ func (p *Parser) updateOrder(internal storage.TradeLog, parsed []interface{}) (s func decay(startAmount, endAmount, decayStartTime, decayEndTime, blockTime *big.Int) (decayedAmount *big.Int) { decayedAmount = new(big.Int) - if decayEndTime.Cmp(blockTime) <= 0 { + if startAmount.Cmp(endAmount) == 0 { + return startAmount + } else if decayEndTime.Cmp(blockTime) <= 0 { decayedAmount.Set(endAmount) } else if decayStartTime.Cmp(blockTime) >= 0 { decayedAmount.Set(startAmount) @@ -293,7 +289,7 @@ func decay(startAmount, endAmount, decayStartTime, decayEndTime, blockTime *big. decayedAmount = new(big.Int).Sub(startAmount, mulDiv(diff, elapsed, duration)) } else { diff := new(big.Int).Sub(endAmount, startAmount) - decayedAmount = new(big.Int).Add(startAmount, mulDiv(diff, elapsed, duration)) + decayedAmount = new(big.Int).Add(startAmount, mulDivUp(diff, elapsed, duration)) } } return @@ -307,6 +303,16 @@ func mulDiv(a, b, c *big.Int) *big.Int { return new(big.Int).Div(new(big.Int).Mul(a, b), c) } +func mulDivUp(x, y, denominator *big.Int) *big.Int { + product := new(big.Int).Mul(x, y) + remainder := new(big.Int).Mod(product, denominator) + result := new(big.Int).Div(product, denominator) + if remainder.Cmp(big.NewInt(0)) > 0 { + result.Add(result, big.NewInt(1)) + } + return result +} + // func checkExclusivity(exclusive, sender common.Address, exclusivityEndTime, ts uint64) bool { // return exclusive == common.Address{} || ts > exclusivityEndTime || exclusive == sender // } diff --git a/pkg/parser/uniswapx/uniswap_test.go b/pkg/parser/uniswapx/uniswap_test.go index dfe9024..67aa724 100644 --- a/pkg/parser/uniswapx/uniswap_test.go +++ b/pkg/parser/uniswapx/uniswap_test.go @@ -27,9 +27,7 @@ func TestFetchEvent(t *testing.T) { traceCalls := tracecall.NewCache(rpcnode.NewClient(ethClient)) p := MustNewParser(traceCalls) require.Equal(t, p.abi.Events[FilledEvent].ID, common.HexToHash("0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66")) - client, err := ethclient.Dial("https://ethereum.kyberengineering.io") - require.NoError(t, err) - logs, err := client.FilterLogs(context.Background(), ethereum.FilterQuery{ + logs, err := ethClient.FilterLogs(context.Background(), ethereum.FilterQuery{ BlockHash: nil, FromBlock: big.NewInt(19719300), ToBlock: big.NewInt(19719300), diff --git a/pkg/parser/uniswapx_v1/abi.json b/pkg/parser/uniswapx_v1/abi.json new file mode 100644 index 0000000..1b05075 --- /dev/null +++ b/pkg/parser/uniswapx_v1/abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IPermit2","name":"_permit2","type":"address"},{"internalType":"address","name":"_protocolFeeOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DeadlineBeforeEndTime","type":"error"},{"inputs":[],"name":"DeadlinePassed","type":"error"},{"inputs":[{"internalType":"address","name":"duplicateToken","type":"address"}],"name":"DuplicateFeeOutput","type":"error"},{"inputs":[],"name":"EndTimeBeforeStartTime","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"FeeTooLarge","type":"error"},{"inputs":[],"name":"IncorrectAmounts","type":"error"},{"inputs":[],"name":"InputAndOutputDecay","type":"error"},{"inputs":[],"name":"InsufficientEth","type":"error"},{"inputs":[{"internalType":"address","name":"feeToken","type":"address"}],"name":"InvalidFeeToken","type":"error"},{"inputs":[],"name":"InvalidReactor","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NoExclusiveOverride","type":"error"},{"inputs":[],"name":"OrderEndTimeBeforeStartTime","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"filler","type":"address"},{"indexed":true,"internalType":"address","name":"swapper","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"Fill","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldFeeController","type":"address"},{"indexed":false,"internalType":"address","name":"newFeeController","type":"address"}],"name":"ProtocolFeeControllerSet","type":"event"},{"inputs":[{"components":[{"internalType":"bytes","name":"order","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct SignedOrder","name":"order","type":"tuple"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"order","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct SignedOrder[]","name":"orders","type":"tuple[]"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"order","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct SignedOrder[]","name":"orders","type":"tuple[]"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"name":"executeBatchWithCallback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"order","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct SignedOrder","name":"order","type":"tuple"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"name":"executeWithCallback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeController","outputs":[{"internalType":"contract IProtocolFeeController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"contract IPermit2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newFeeController","type":"address"}],"name":"setProtocolFeeController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] diff --git a/pkg/parser/uniswapx_v1/gen.sh b/pkg/parser/uniswapx_v1/gen.sh new file mode 100755 index 0000000..d51d7ea --- /dev/null +++ b/pkg/parser/uniswapx_v1/gen.sh @@ -0,0 +1 @@ +abigen --abi=abi.json --pkg=uniswapxv1 --out=uniswapx.go diff --git a/pkg/parser/uniswapx_v1/parser.go b/pkg/parser/uniswapx_v1/parser.go new file mode 100644 index 0000000..b2650ac --- /dev/null +++ b/pkg/parser/uniswapx_v1/parser.go @@ -0,0 +1,297 @@ +package uniswapxv1 + +import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/KyberNetwork/tradelogs/pkg/types" + tradingTypes "github.com/KyberNetwork/tradinglib/pkg/types" + + "github.com/KyberNetwork/tradelogs/pkg/decoder" + "github.com/KyberNetwork/tradelogs/pkg/parser" + "github.com/KyberNetwork/tradelogs/pkg/storage" + "github.com/KyberNetwork/tradelogs/pkg/tracecall" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + ethereumTypes "github.com/ethereum/go-ethereum/core/types" +) + +const ( + FilledEvent = "Fill" +) + +type ResolvedOrder struct { + Info struct { + Reactor common.Address "json:\"reactor\"" + Swapper common.Address "json:\"swapper\"" + Nonce *big.Int "json:\"nonce\"" + Deadline *big.Int "json:\"deadline\"" + AdditionalValidationContract common.Address "json:\"additionalValidationContract\"" + AdditionalValidationData []uint8 "json:\"additionalValidationData\"" + } "json:\"info\"" + DecayStartTime *big.Int "json:\"decayStartTime\"" + DecayEndTime *big.Int "json:\"decayEndTime\"" + ExclusiveFiller common.Address "json:\"exclusiveFiller\"" + ExclusivityOverrideBps *big.Int "json:\"exclusivityOverrideBps\"" + InputToken common.Address "json:\"inputToken\"" + InputStartAmount *big.Int "json:\"inputStartAmount\"" + InputEndAmount *big.Int "json:\"inputEndAmount\"" + Outputs []struct { + Token common.Address "json:\"token\"" + StartAmount *big.Int "json:\"startAmount\"" + EndAmount *big.Int "json:\"endAmount\"" + Recipient common.Address "json:\"recipient\"" + } "json:\"outputs\"" +} + +type Parser struct { + abi *abi.ABI + ps *Uniswapxv1Filterer + eventHash string + traceCalls *tracecall.Cache + orderArguments abi.Arguments +} + +func MustNewParser(cache *tracecall.Cache) *Parser { + ps, err := NewUniswapxv1Filterer(common.Address{}, nil) + if err != nil { + panic(err) + } + ab, err := Uniswapxv1MetaData.GetAbi() + if err != nil { + panic(err) + } + event, ok := ab.Events[FilledEvent] + if !ok { + panic(fmt.Sprintf("no such event: %s", FilledEvent)) + } + + orderTuple, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + {Name: "info", Type: "tuple", Components: []abi.ArgumentMarshaling{ + {Name: "reactor", Type: "address"}, + {Name: "swapper", Type: "address"}, + {Name: "nonce", Type: "uint256"}, + {Name: "deadline", Type: "uint256"}, + {Name: "additionalValidationContract", Type: "address"}, + {Name: "additionalValidationData", Type: "bytes"}}, + }, + {Name: "decayStartTime", Type: "uint256"}, + {Name: "decayEndTime", Type: "uint256"}, + {Name: "exclusiveFiller", Type: "address"}, + {Name: "exclusivityOverrideBps", Type: "uint256"}, + {Name: "inputToken", Type: "address"}, + {Name: "inputStartAmount", Type: "uint256"}, + {Name: "inputEndAmount", Type: "uint256"}, + {Name: "outputs", Type: "tuple[]", Components: []abi.ArgumentMarshaling{ + {Name: "token", Type: "address"}, + {Name: "startAmount", Type: "uint256"}, + {Name: "endAmount", Type: "uint256"}, + {Name: "recipient", Type: "address"}, + }}, + }) + if err != nil { + panic("cant create order abi type") + } + + return &Parser{ + ps: ps, + abi: ab, + eventHash: event.ID.String(), + traceCalls: cache, + orderArguments: abi.Arguments{{Type: orderTuple}}, + } +} + +func (p *Parser) Topics() []string { + return []string{ + p.eventHash, + } +} + +func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { + order, err := p.buildOrderByLog(log, blockTime) + if err != nil { + return storage.TradeLog{}, err + } + + order, err = p.detectRfqTrade(order) + if err != nil { + return order, err + } + return order, nil +} + +func (p *Parser) buildOrderByLog(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { + if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { + return storage.TradeLog{}, parser.ErrInvalidTopic + } + e, err := p.ps.ParseFill(log) + if err != nil { + return storage.TradeLog{}, err + } + order := storage.TradeLog{ + OrderHash: common.Hash(e.OrderHash).String(), + ContractAddress: e.Raw.Address.String(), + BlockNumber: e.Raw.BlockNumber, + TxHash: e.Raw.TxHash.String(), + LogIndex: uint64(e.Raw.Index), + Timestamp: blockTime * 1000, + EventHash: p.eventHash, + Maker: e.Filler.String(), + Taker: e.Swapper.String(), + } + return order, nil +} + +func (p *Parser) detectRfqTrade(order storage.TradeLog) (storage.TradeLog, error) { + traceCall, err := p.traceCalls.GetTraceCall(order.TxHash) + if err != nil { + return order, err + } + + order, err = p.recursiveDetectRFQTrades(order, traceCall) + if err != nil { + return order, err + } + return order, nil +} + +func (p *Parser) recursiveDetectRFQTrades(order storage.TradeLog, call types.CallFrame) (storage.TradeLog, error) { + for _, l := range call.Logs { + if len(l.Topics) < 2 { + continue + } + if l.Topics[0].String() != p.eventHash || l.Topics[1].String() != order.OrderHash { + continue + } + input, err := decoder.Decode(p.abi, call.Input) + if err != nil { + continue + } + if len(input.Params) == 0 { + continue + } + inputOrder, ok := input.Params[0].Value.(struct { + Order []uint8 `json:"order"` + Sig []uint8 `json:"sig"` + }) + if !ok { + inputOrders, ok := input.Params[0].Value.([]struct { + Order []uint8 `json:"order"` + Sig []uint8 `json:"sig"` + }) + if !ok || len(inputOrders) == 0 { + continue + } + inputOrder = inputOrders[0] + } + parsedOrder, err := p.orderArguments.Unpack(inputOrder.Order) + if err != nil { + continue + } + finalOrder, err := p.updateOrder(order, parsedOrder) + if err != nil { + continue + } + return finalOrder, nil + } + + for i := range call.Calls { + order, err := p.recursiveDetectRFQTrades(order, call.Calls[i]) + if err == nil { + return order, nil + } + } + traceData, _ := json.Marshal(call) + return order, fmt.Errorf("%w %s", parser.ErrNotFoundTrade, string(traceData)) +} + +func (p *Parser) updateOrder(internal storage.TradeLog, parsed []interface{}) (storage.TradeLog, error) { + data, err := json.Marshal(parsed) + if err != nil { + return storage.TradeLog{}, err + } + var resolvedOrder []ResolvedOrder + if err = json.Unmarshal(data, &resolvedOrder); err != nil { + return storage.TradeLog{}, err + } + if len(resolvedOrder) == 0 || len(resolvedOrder[0].Outputs) == 0 { + return storage.TradeLog{}, err + } + order := resolvedOrder[0] + internal.TakerToken = order.InputToken.String() + internal.TakerTokenAmount = decay(order.InputStartAmount, + order.InputEndAmount, + order.DecayStartTime, + order.DecayEndTime, + big.NewInt(int64(internal.Timestamp/1000))).String() + internal.MakerToken = order.Outputs[0].Token.String() + + makerAmount := big.NewInt(0) + for _, o := range order.Outputs { + makerAmount = makerAmount.Add(makerAmount, decay(o.StartAmount, o.EndAmount, + order.DecayStartTime, order.DecayEndTime, + big.NewInt(int64(internal.Timestamp/1000)))) + } + internal.MakerTokenAmount = makerAmount.String() + + return internal, nil +} + +func decay(startAmount, endAmount, decayStartTime, decayEndTime, blockTime *big.Int) (decayedAmount *big.Int) { + decayedAmount = new(big.Int) + + if decayEndTime.Cmp(blockTime) <= 0 { + decayedAmount.Set(endAmount) + } else if decayStartTime.Cmp(blockTime) >= 0 { + decayedAmount.Set(startAmount) + } else { + elapsed := new(big.Int).Sub(blockTime, decayStartTime) + duration := new(big.Int).Sub(decayEndTime, decayStartTime) + + if endAmount.Cmp(startAmount) < 0 { + diff := new(big.Int).Sub(startAmount, endAmount) + decayedAmount = new(big.Int).Sub(startAmount, mulDiv(diff, elapsed, duration)) + } else { + diff := new(big.Int).Sub(endAmount, startAmount) + decayedAmount = new(big.Int).Add(startAmount, mulDiv(diff, elapsed, duration)) + } + } + return +} + +func mulDiv(a, b, c *big.Int) *big.Int { + return new(big.Int).Div(new(big.Int).Mul(a, b), c) +} + +func (p *Parser) Exchange() string { + return parser.ExUniswapXV1 +} + +func (p *Parser) UseTraceCall() bool { + return true +} + +func (p *Parser) ParseWithCallFrame(callFrame *tradingTypes.CallFrame, log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { + if callFrame == nil { + return storage.TradeLog{}, errors.New("missing call frame") + } + order, err := p.buildOrderByLog(log, blockTime) + if err != nil { + return storage.TradeLog{}, err + } + order, err = p.recursiveDetectRFQTrades(order, types.ConvertCallFrame(callFrame)) + if err != nil { + return order, err + } + return order, nil +} + +func (p *Parser) LogFromExchange(log ethereumTypes.Log) bool { + return strings.EqualFold(log.Address.String(), parser.AddrUniswapXV1) && + len(log.Topics) > 0 && + strings.EqualFold(log.Topics[0].String(), p.eventHash) +} diff --git a/pkg/parser/uniswapx_v1/uniswap_test.go b/pkg/parser/uniswapx_v1/uniswap_test.go new file mode 100644 index 0000000..5367241 --- /dev/null +++ b/pkg/parser/uniswapx_v1/uniswap_test.go @@ -0,0 +1,70 @@ +package uniswapxv1 // nolint: testpackage + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "testing" + + "github.com/KyberNetwork/tradelogs/pkg/rpcnode" + "github.com/KyberNetwork/tradelogs/pkg/tracecall" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const rpcURL = "" + +func TestFetchEvent(t *testing.T) { + t.Skip("Need to add the rpc url that enables the trace call JSON-RPC") + ethClient, err := ethclient.Dial(rpcURL) + if err != nil { + panic(err) + } + traceCalls := tracecall.NewCache(rpcnode.NewClient(ethClient)) + p := MustNewParser(traceCalls) + require.Equal(t, p.abi.Events[FilledEvent].ID, common.HexToHash("0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66")) + logs, err := ethClient.FilterLogs(context.Background(), ethereum.FilterQuery{ + BlockHash: nil, + FromBlock: big.NewInt(20488655), + ToBlock: big.NewInt(20488655), + Addresses: nil, + Topics: [][]common.Hash{ + { + p.abi.Events[FilledEvent].ID, + }, + }, + }) + require.NoError(t, err) + d, err := json.Marshal(logs) + require.NoError(t, err) + t.Log(string(d)) +} + +func TestParseEvent(t *testing.T) { + t.Skip("Need to add the rpc url that enables the trace call JSON-RPC") + event := types.Log{} + eventRaw := `{"address":"0x6000da47483062a0d734ba3dc7576ce6a0b645c4","topics":["0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66","0xc356060ff3e60da206578d00e9cc9145cb36889fd412a7f34ddb1435e85e689e","0x000000000000000000000000def4a2438df14050d98c0e9d4d93000000890bb2","0x000000000000000000000000fe87dfcd8164adf6437edb236ab42fce19238ea6"],"data":"0x046832e66de00af695779aa4b76a837f8e31026be2ee4f4ffbdb06860ca6fd08","blockNumber":"0x138a1cf","transactionHash":"0x7a45f257e24145dd06d25dc8f77384a5e08c5c5c6220bb3f379764cfa7d30735","transactionIndex":"0x1","blockHash":"0x6bfbbcf9ec00f478c20ad6c706b0c1f9b35111f5dade8bf7ccac6671cb0d5764","logIndex":"0x8","removed":false}` + err := json.Unmarshal([]byte(eventRaw), &event) + require.NoError(t, err) + ethClient, err := ethclient.Dial(rpcURL) + if err != nil { + panic(err) + } + traceCalls := tracecall.NewCache(rpcnode.NewClient(ethClient)) + p := MustNewParser(traceCalls) + log, err := p.Parse(event, 1713889895) + require.NoError(t, err) + fmt.Printf("%+v\n", log) + require.Equal(t, log.EventHash, p.eventHash) + require.Equal(t, log.Maker, "0xdEF4a2438DF14050D98C0e9d4D93000000890BB2") + require.Equal(t, log.Taker, "0xfE87Dfcd8164aDF6437edb236aB42fcE19238Ea6") + require.Equal(t, log.MakerTokenAmount, "100419300000000000") + require.Equal(t, log.MakerToken, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + require.Equal(t, log.TakerTokenAmount, "30000000000000000") + require.Equal(t, log.TakerToken, "0xEE16bd5e21cd5D27D0EAfdabbCCA0A438e97E46C") + t.Log(log) +} diff --git a/pkg/parser/uniswapx_v1/uniswapx.go b/pkg/parser/uniswapx_v1/uniswapx.go new file mode 100644 index 0000000..4959b0c --- /dev/null +++ b/pkg/parser/uniswapx_v1/uniswapx.go @@ -0,0 +1,878 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package uniswapxv1 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// SignedOrder is an auto generated low-level Go binding around an user-defined struct. +type SignedOrder struct { + Order []byte + Sig []byte +} + +// Uniswapxv1MetaData contains all meta data concerning the Uniswapxv1 contract. +var Uniswapxv1MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIPermit2\",\"name\":\"_permit2\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_protocolFeeOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DeadlineBeforeEndTime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlinePassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"duplicateToken\",\"type\":\"address\"}],\"name\":\"DuplicateFeeOutput\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EndTimeBeforeStartTime\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"FeeTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectAmounts\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InputAndOutputDecay\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientEth\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"InvalidFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReactor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoExclusiveOverride\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OrderEndTimeBeforeStartTime\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"orderHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"filler\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"swapper\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"name\":\"Fill\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldFeeController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeController\",\"type\":\"address\"}],\"name\":\"ProtocolFeeControllerSet\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"order\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"structSignedOrder\",\"name\":\"order\",\"type\":\"tuple\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"order\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"structSignedOrder[]\",\"name\":\"orders\",\"type\":\"tuple[]\"}],\"name\":\"executeBatch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"order\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"structSignedOrder[]\",\"name\":\"orders\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackData\",\"type\":\"bytes\"}],\"name\":\"executeBatchWithCallback\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"order\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"structSignedOrder\",\"name\":\"order\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"callbackData\",\"type\":\"bytes\"}],\"name\":\"executeWithCallback\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeController\",\"outputs\":[{\"internalType\":\"contractIProtocolFeeController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"permit2\",\"outputs\":[{\"internalType\":\"contractIPermit2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newFeeController\",\"type\":\"address\"}],\"name\":\"setProtocolFeeController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", +} + +// Uniswapxv1ABI is the input ABI used to generate the binding from. +// Deprecated: Use Uniswapxv1MetaData.ABI instead. +var Uniswapxv1ABI = Uniswapxv1MetaData.ABI + +// Uniswapxv1 is an auto generated Go binding around an Ethereum contract. +type Uniswapxv1 struct { + Uniswapxv1Caller // Read-only binding to the contract + Uniswapxv1Transactor // Write-only binding to the contract + Uniswapxv1Filterer // Log filterer for contract events +} + +// Uniswapxv1Caller is an auto generated read-only Go binding around an Ethereum contract. +type Uniswapxv1Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Uniswapxv1Transactor is an auto generated write-only Go binding around an Ethereum contract. +type Uniswapxv1Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Uniswapxv1Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type Uniswapxv1Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// Uniswapxv1Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type Uniswapxv1Session struct { + Contract *Uniswapxv1 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Uniswapxv1CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type Uniswapxv1CallerSession struct { + Contract *Uniswapxv1Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// Uniswapxv1TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type Uniswapxv1TransactorSession struct { + Contract *Uniswapxv1Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// Uniswapxv1Raw is an auto generated low-level Go binding around an Ethereum contract. +type Uniswapxv1Raw struct { + Contract *Uniswapxv1 // Generic contract binding to access the raw methods on +} + +// Uniswapxv1CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type Uniswapxv1CallerRaw struct { + Contract *Uniswapxv1Caller // Generic read-only contract binding to access the raw methods on +} + +// Uniswapxv1TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type Uniswapxv1TransactorRaw struct { + Contract *Uniswapxv1Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewUniswapxv1 creates a new instance of Uniswapxv1, bound to a specific deployed contract. +func NewUniswapxv1(address common.Address, backend bind.ContractBackend) (*Uniswapxv1, error) { + contract, err := bindUniswapxv1(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Uniswapxv1{Uniswapxv1Caller: Uniswapxv1Caller{contract: contract}, Uniswapxv1Transactor: Uniswapxv1Transactor{contract: contract}, Uniswapxv1Filterer: Uniswapxv1Filterer{contract: contract}}, nil +} + +// NewUniswapxv1Caller creates a new read-only instance of Uniswapxv1, bound to a specific deployed contract. +func NewUniswapxv1Caller(address common.Address, caller bind.ContractCaller) (*Uniswapxv1Caller, error) { + contract, err := bindUniswapxv1(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &Uniswapxv1Caller{contract: contract}, nil +} + +// NewUniswapxv1Transactor creates a new write-only instance of Uniswapxv1, bound to a specific deployed contract. +func NewUniswapxv1Transactor(address common.Address, transactor bind.ContractTransactor) (*Uniswapxv1Transactor, error) { + contract, err := bindUniswapxv1(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &Uniswapxv1Transactor{contract: contract}, nil +} + +// NewUniswapxv1Filterer creates a new log filterer instance of Uniswapxv1, bound to a specific deployed contract. +func NewUniswapxv1Filterer(address common.Address, filterer bind.ContractFilterer) (*Uniswapxv1Filterer, error) { + contract, err := bindUniswapxv1(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &Uniswapxv1Filterer{contract: contract}, nil +} + +// bindUniswapxv1 binds a generic wrapper to an already deployed contract. +func bindUniswapxv1(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := Uniswapxv1MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Uniswapxv1 *Uniswapxv1Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Uniswapxv1.Contract.Uniswapxv1Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Uniswapxv1 *Uniswapxv1Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Uniswapxv1.Contract.Uniswapxv1Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Uniswapxv1 *Uniswapxv1Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Uniswapxv1.Contract.Uniswapxv1Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Uniswapxv1 *Uniswapxv1CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Uniswapxv1.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Uniswapxv1 *Uniswapxv1TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Uniswapxv1.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Uniswapxv1 *Uniswapxv1TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Uniswapxv1.Contract.contract.Transact(opts, method, params...) +} + +// FeeController is a free data retrieval call binding the contract method 0x6999b377. +// +// Solidity: function feeController() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Caller) FeeController(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Uniswapxv1.contract.Call(opts, &out, "feeController") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// FeeController is a free data retrieval call binding the contract method 0x6999b377. +// +// Solidity: function feeController() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Session) FeeController() (common.Address, error) { + return _Uniswapxv1.Contract.FeeController(&_Uniswapxv1.CallOpts) +} + +// FeeController is a free data retrieval call binding the contract method 0x6999b377. +// +// Solidity: function feeController() view returns(address) +func (_Uniswapxv1 *Uniswapxv1CallerSession) FeeController() (common.Address, error) { + return _Uniswapxv1.Contract.FeeController(&_Uniswapxv1.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Caller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Uniswapxv1.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Session) Owner() (common.Address, error) { + return _Uniswapxv1.Contract.Owner(&_Uniswapxv1.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Uniswapxv1 *Uniswapxv1CallerSession) Owner() (common.Address, error) { + return _Uniswapxv1.Contract.Owner(&_Uniswapxv1.CallOpts) +} + +// Permit2 is a free data retrieval call binding the contract method 0x12261ee7. +// +// Solidity: function permit2() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Caller) Permit2(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Uniswapxv1.contract.Call(opts, &out, "permit2") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Permit2 is a free data retrieval call binding the contract method 0x12261ee7. +// +// Solidity: function permit2() view returns(address) +func (_Uniswapxv1 *Uniswapxv1Session) Permit2() (common.Address, error) { + return _Uniswapxv1.Contract.Permit2(&_Uniswapxv1.CallOpts) +} + +// Permit2 is a free data retrieval call binding the contract method 0x12261ee7. +// +// Solidity: function permit2() view returns(address) +func (_Uniswapxv1 *Uniswapxv1CallerSession) Permit2() (common.Address, error) { + return _Uniswapxv1.Contract.Permit2(&_Uniswapxv1.CallOpts) +} + +// Execute is a paid mutator transaction binding the contract method 0x3f62192e. +// +// Solidity: function execute((bytes,bytes) order) payable returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) Execute(opts *bind.TransactOpts, order SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "execute", order) +} + +// Execute is a paid mutator transaction binding the contract method 0x3f62192e. +// +// Solidity: function execute((bytes,bytes) order) payable returns() +func (_Uniswapxv1 *Uniswapxv1Session) Execute(order SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.Contract.Execute(&_Uniswapxv1.TransactOpts, order) +} + +// Execute is a paid mutator transaction binding the contract method 0x3f62192e. +// +// Solidity: function execute((bytes,bytes) order) payable returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) Execute(order SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.Contract.Execute(&_Uniswapxv1.TransactOpts, order) +} + +// ExecuteBatch is a paid mutator transaction binding the contract method 0x0d7a16c3. +// +// Solidity: function executeBatch((bytes,bytes)[] orders) payable returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) ExecuteBatch(opts *bind.TransactOpts, orders []SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "executeBatch", orders) +} + +// ExecuteBatch is a paid mutator transaction binding the contract method 0x0d7a16c3. +// +// Solidity: function executeBatch((bytes,bytes)[] orders) payable returns() +func (_Uniswapxv1 *Uniswapxv1Session) ExecuteBatch(orders []SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteBatch(&_Uniswapxv1.TransactOpts, orders) +} + +// ExecuteBatch is a paid mutator transaction binding the contract method 0x0d7a16c3. +// +// Solidity: function executeBatch((bytes,bytes)[] orders) payable returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) ExecuteBatch(orders []SignedOrder) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteBatch(&_Uniswapxv1.TransactOpts, orders) +} + +// ExecuteBatchWithCallback is a paid mutator transaction binding the contract method 0x13fb72c7. +// +// Solidity: function executeBatchWithCallback((bytes,bytes)[] orders, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) ExecuteBatchWithCallback(opts *bind.TransactOpts, orders []SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "executeBatchWithCallback", orders, callbackData) +} + +// ExecuteBatchWithCallback is a paid mutator transaction binding the contract method 0x13fb72c7. +// +// Solidity: function executeBatchWithCallback((bytes,bytes)[] orders, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1Session) ExecuteBatchWithCallback(orders []SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteBatchWithCallback(&_Uniswapxv1.TransactOpts, orders, callbackData) +} + +// ExecuteBatchWithCallback is a paid mutator transaction binding the contract method 0x13fb72c7. +// +// Solidity: function executeBatchWithCallback((bytes,bytes)[] orders, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) ExecuteBatchWithCallback(orders []SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteBatchWithCallback(&_Uniswapxv1.TransactOpts, orders, callbackData) +} + +// ExecuteWithCallback is a paid mutator transaction binding the contract method 0x0d335884. +// +// Solidity: function executeWithCallback((bytes,bytes) order, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) ExecuteWithCallback(opts *bind.TransactOpts, order SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "executeWithCallback", order, callbackData) +} + +// ExecuteWithCallback is a paid mutator transaction binding the contract method 0x0d335884. +// +// Solidity: function executeWithCallback((bytes,bytes) order, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1Session) ExecuteWithCallback(order SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteWithCallback(&_Uniswapxv1.TransactOpts, order, callbackData) +} + +// ExecuteWithCallback is a paid mutator transaction binding the contract method 0x0d335884. +// +// Solidity: function executeWithCallback((bytes,bytes) order, bytes callbackData) payable returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) ExecuteWithCallback(order SignedOrder, callbackData []byte) (*types.Transaction, error) { + return _Uniswapxv1.Contract.ExecuteWithCallback(&_Uniswapxv1.TransactOpts, order, callbackData) +} + +// SetProtocolFeeController is a paid mutator transaction binding the contract method 0x2d771389. +// +// Solidity: function setProtocolFeeController(address _newFeeController) returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) SetProtocolFeeController(opts *bind.TransactOpts, _newFeeController common.Address) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "setProtocolFeeController", _newFeeController) +} + +// SetProtocolFeeController is a paid mutator transaction binding the contract method 0x2d771389. +// +// Solidity: function setProtocolFeeController(address _newFeeController) returns() +func (_Uniswapxv1 *Uniswapxv1Session) SetProtocolFeeController(_newFeeController common.Address) (*types.Transaction, error) { + return _Uniswapxv1.Contract.SetProtocolFeeController(&_Uniswapxv1.TransactOpts, _newFeeController) +} + +// SetProtocolFeeController is a paid mutator transaction binding the contract method 0x2d771389. +// +// Solidity: function setProtocolFeeController(address _newFeeController) returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) SetProtocolFeeController(_newFeeController common.Address) (*types.Transaction, error) { + return _Uniswapxv1.Contract.SetProtocolFeeController(&_Uniswapxv1.TransactOpts, _newFeeController) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Uniswapxv1.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Uniswapxv1 *Uniswapxv1Session) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Uniswapxv1.Contract.TransferOwnership(&_Uniswapxv1.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Uniswapxv1.Contract.TransferOwnership(&_Uniswapxv1.TransactOpts, newOwner) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Uniswapxv1 *Uniswapxv1Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Uniswapxv1.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Uniswapxv1 *Uniswapxv1Session) Receive() (*types.Transaction, error) { + return _Uniswapxv1.Contract.Receive(&_Uniswapxv1.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_Uniswapxv1 *Uniswapxv1TransactorSession) Receive() (*types.Transaction, error) { + return _Uniswapxv1.Contract.Receive(&_Uniswapxv1.TransactOpts) +} + +// Uniswapxv1FillIterator is returned from FilterFill and is used to iterate over the raw logs and unpacked data for Fill events raised by the Uniswapxv1 contract. +type Uniswapxv1FillIterator struct { + Event *Uniswapxv1Fill // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Uniswapxv1FillIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1Fill) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1Fill) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Uniswapxv1FillIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Uniswapxv1FillIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Uniswapxv1Fill represents a Fill event raised by the Uniswapxv1 contract. +type Uniswapxv1Fill struct { + OrderHash [32]byte + Filler common.Address + Swapper common.Address + Nonce *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterFill is a free log retrieval operation binding the contract event 0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66. +// +// Solidity: event Fill(bytes32 indexed orderHash, address indexed filler, address indexed swapper, uint256 nonce) +func (_Uniswapxv1 *Uniswapxv1Filterer) FilterFill(opts *bind.FilterOpts, orderHash [][32]byte, filler []common.Address, swapper []common.Address) (*Uniswapxv1FillIterator, error) { + + var orderHashRule []interface{} + for _, orderHashItem := range orderHash { + orderHashRule = append(orderHashRule, orderHashItem) + } + var fillerRule []interface{} + for _, fillerItem := range filler { + fillerRule = append(fillerRule, fillerItem) + } + var swapperRule []interface{} + for _, swapperItem := range swapper { + swapperRule = append(swapperRule, swapperItem) + } + + logs, sub, err := _Uniswapxv1.contract.FilterLogs(opts, "Fill", orderHashRule, fillerRule, swapperRule) + if err != nil { + return nil, err + } + return &Uniswapxv1FillIterator{contract: _Uniswapxv1.contract, event: "Fill", logs: logs, sub: sub}, nil +} + +// WatchFill is a free log subscription operation binding the contract event 0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66. +// +// Solidity: event Fill(bytes32 indexed orderHash, address indexed filler, address indexed swapper, uint256 nonce) +func (_Uniswapxv1 *Uniswapxv1Filterer) WatchFill(opts *bind.WatchOpts, sink chan<- *Uniswapxv1Fill, orderHash [][32]byte, filler []common.Address, swapper []common.Address) (event.Subscription, error) { + + var orderHashRule []interface{} + for _, orderHashItem := range orderHash { + orderHashRule = append(orderHashRule, orderHashItem) + } + var fillerRule []interface{} + for _, fillerItem := range filler { + fillerRule = append(fillerRule, fillerItem) + } + var swapperRule []interface{} + for _, swapperItem := range swapper { + swapperRule = append(swapperRule, swapperItem) + } + + logs, sub, err := _Uniswapxv1.contract.WatchLogs(opts, "Fill", orderHashRule, fillerRule, swapperRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Uniswapxv1Fill) + if err := _Uniswapxv1.contract.UnpackLog(event, "Fill", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseFill is a log parse operation binding the contract event 0x78ad7ec0e9f89e74012afa58738b6b661c024cb0fd185ee2f616c0a28924bd66. +// +// Solidity: event Fill(bytes32 indexed orderHash, address indexed filler, address indexed swapper, uint256 nonce) +func (_Uniswapxv1 *Uniswapxv1Filterer) ParseFill(log types.Log) (*Uniswapxv1Fill, error) { + event := new(Uniswapxv1Fill) + if err := _Uniswapxv1.contract.UnpackLog(event, "Fill", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Uniswapxv1OwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Uniswapxv1 contract. +type Uniswapxv1OwnershipTransferredIterator struct { + Event *Uniswapxv1OwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Uniswapxv1OwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1OwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Uniswapxv1OwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Uniswapxv1OwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Uniswapxv1OwnershipTransferred represents a OwnershipTransferred event raised by the Uniswapxv1 contract. +type Uniswapxv1OwnershipTransferred struct { + User common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed user, address indexed newOwner) +func (_Uniswapxv1 *Uniswapxv1Filterer) FilterOwnershipTransferred(opts *bind.FilterOpts, user []common.Address, newOwner []common.Address) (*Uniswapxv1OwnershipTransferredIterator, error) { + + var userRule []interface{} + for _, userItem := range user { + userRule = append(userRule, userItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Uniswapxv1.contract.FilterLogs(opts, "OwnershipTransferred", userRule, newOwnerRule) + if err != nil { + return nil, err + } + return &Uniswapxv1OwnershipTransferredIterator{contract: _Uniswapxv1.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed user, address indexed newOwner) +func (_Uniswapxv1 *Uniswapxv1Filterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *Uniswapxv1OwnershipTransferred, user []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var userRule []interface{} + for _, userItem := range user { + userRule = append(userRule, userItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Uniswapxv1.contract.WatchLogs(opts, "OwnershipTransferred", userRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Uniswapxv1OwnershipTransferred) + if err := _Uniswapxv1.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed user, address indexed newOwner) +func (_Uniswapxv1 *Uniswapxv1Filterer) ParseOwnershipTransferred(log types.Log) (*Uniswapxv1OwnershipTransferred, error) { + event := new(Uniswapxv1OwnershipTransferred) + if err := _Uniswapxv1.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// Uniswapxv1ProtocolFeeControllerSetIterator is returned from FilterProtocolFeeControllerSet and is used to iterate over the raw logs and unpacked data for ProtocolFeeControllerSet events raised by the Uniswapxv1 contract. +type Uniswapxv1ProtocolFeeControllerSetIterator struct { + Event *Uniswapxv1ProtocolFeeControllerSet // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *Uniswapxv1ProtocolFeeControllerSetIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1ProtocolFeeControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(Uniswapxv1ProtocolFeeControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *Uniswapxv1ProtocolFeeControllerSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *Uniswapxv1ProtocolFeeControllerSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// Uniswapxv1ProtocolFeeControllerSet represents a ProtocolFeeControllerSet event raised by the Uniswapxv1 contract. +type Uniswapxv1ProtocolFeeControllerSet struct { + OldFeeController common.Address + NewFeeController common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterProtocolFeeControllerSet is a free log retrieval operation binding the contract event 0xb904ae9529e373e48bc82df4326cceaf1b4c472babf37f5b7dec46fecc6b53e0. +// +// Solidity: event ProtocolFeeControllerSet(address oldFeeController, address newFeeController) +func (_Uniswapxv1 *Uniswapxv1Filterer) FilterProtocolFeeControllerSet(opts *bind.FilterOpts) (*Uniswapxv1ProtocolFeeControllerSetIterator, error) { + + logs, sub, err := _Uniswapxv1.contract.FilterLogs(opts, "ProtocolFeeControllerSet") + if err != nil { + return nil, err + } + return &Uniswapxv1ProtocolFeeControllerSetIterator{contract: _Uniswapxv1.contract, event: "ProtocolFeeControllerSet", logs: logs, sub: sub}, nil +} + +// WatchProtocolFeeControllerSet is a free log subscription operation binding the contract event 0xb904ae9529e373e48bc82df4326cceaf1b4c472babf37f5b7dec46fecc6b53e0. +// +// Solidity: event ProtocolFeeControllerSet(address oldFeeController, address newFeeController) +func (_Uniswapxv1 *Uniswapxv1Filterer) WatchProtocolFeeControllerSet(opts *bind.WatchOpts, sink chan<- *Uniswapxv1ProtocolFeeControllerSet) (event.Subscription, error) { + + logs, sub, err := _Uniswapxv1.contract.WatchLogs(opts, "ProtocolFeeControllerSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(Uniswapxv1ProtocolFeeControllerSet) + if err := _Uniswapxv1.contract.UnpackLog(event, "ProtocolFeeControllerSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseProtocolFeeControllerSet is a log parse operation binding the contract event 0xb904ae9529e373e48bc82df4326cceaf1b4c472babf37f5b7dec46fecc6b53e0. +// +// Solidity: event ProtocolFeeControllerSet(address oldFeeController, address newFeeController) +func (_Uniswapxv1 *Uniswapxv1Filterer) ParseProtocolFeeControllerSet(log types.Log) (*Uniswapxv1ProtocolFeeControllerSet, error) { + event := new(Uniswapxv1ProtocolFeeControllerSet) + if err := _Uniswapxv1.contract.UnpackLog(event, "ProtocolFeeControllerSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/parser/zxotc/parser.go b/pkg/parser/zxotc/parser.go index 28c7980..c048403 100644 --- a/pkg/parser/zxotc/parser.go +++ b/pkg/parser/zxotc/parser.go @@ -21,8 +21,6 @@ const ( paramName = "order" ) -var ErrInvalidOTCTopic = errors.New("invalid OTCFilled topic") - type Parser struct { abi *abi.ABI ps *ZeroXOTCFilterer @@ -57,7 +55,7 @@ func (p *Parser) Topics() []string { func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { - return storage.TradeLog{}, ErrInvalidOTCTopic + return storage.TradeLog{}, parser.ErrInvalidTopic } o, err := p.ps.ParseOtcOrderFilled(log) if err != nil { diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 5cc7abe..716bba5 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -253,3 +253,16 @@ func (s *Storage) GetErrorLogsSince(t int64) ([]EVMLog, error) { } return result, nil } + +func (s *Storage) RemoveLogUtil(t int64) error { + q, p, err := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). + Delete(errorLogsTable). + Where(squirrel.Lt{"time": t}). + ToSql() + if err != nil { + return err + + } + _, err = s.db.Exec(q, p...) + return err +}