Skip to content

Commit

Permalink
feat: handle partial fill orders
Browse files Browse the repository at this point in the history
  • Loading branch information
tiennampham23 committed Dec 12, 2023
1 parent b2aae4e commit 7c7aacb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
2 changes: 0 additions & 2 deletions internal/types/trace_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ type TraceCallResponse struct {
}

type CallLog struct {
Index uint `json:"index"`
Address common.Address `json:"address"`
Topics []common.Hash `json:"topics"`
Data string `json:"data"`
}

func (l CallLog) ToEthereumLog() ethereumTypes.Log {
return ethereumTypes.Log{
Index: l.Index,
Address: l.Address,
Topics: l.Topics,
Data: common.Hex2Bytes(l.Data),
Expand Down
49 changes: 39 additions & 10 deletions pkg/parser/oneinch/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/KyberNetwork/tradelogs/pkg/storage"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethereumTypes "github.com/ethereum/go-ethereum/core/types"
"strings"
)
Expand Down Expand Up @@ -67,7 +68,7 @@ func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLo
if err != nil {
return storage.TradeLog{}, err
}
res := storage.TradeLog{
order := storage.TradeLog{
OrderHash: common.Hash(e.OrderHash).String(),
MakerTokenAmount: e.MakingAmount.String(),
ContractAddress: e.Raw.Address.String(),
Expand All @@ -78,32 +79,32 @@ func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLo
EventHash: p.eventHash,
}

res, err = p.detectOneInchRfqTrade(res, log.TxHash.String(), blockTime)
order, err = p.detectOneInchRfqTrade(order, log, blockTime)
if err != nil {
return storage.TradeLog{}, err
}
return res, nil
return order, nil
}

func (p *Parser) detectOneInchRfqTrade(order storage.TradeLog, txHash string, blockTimestamp uint64) (storage.TradeLog, error) {
traceCall, err := p.rpcNode.FetchTraceCall(context.Background(), txHash)
func (p *Parser) detectOneInchRfqTrade(order storage.TradeLog, log ethereumTypes.Log, blockTimestamp uint64) (storage.TradeLog, error) {
traceCall, err := p.rpcNode.FetchTraceCall(context.Background(), order.TxHash)
if err != nil {
return order, err
}

order, err = p.recursiveDetectOneInchRFQTrades(order, traceCall, blockTimestamp)
order, err = p.recursiveDetectOneInchRFQTrades(order, log, traceCall, blockTimestamp)
if err != nil {
return order, err
}

return order, nil
}

func (p *Parser) recursiveDetectOneInchRFQTrades(tradeLog storage.TradeLog, traceCall types.CallFrame, blockTimestamp uint64) (storage.TradeLog, error) {
func (p *Parser) recursiveDetectOneInchRFQTrades(tradeLog storage.TradeLog, log ethereumTypes.Log, traceCall types.CallFrame, blockTimestamp uint64) (storage.TradeLog, error) {
var (
err error
)
isOneInchRFQTrade := p.isOneInchRFQTrades(traceCall.Logs)
isOneInchRFQTrade := p.isOneInchRFQTrades(log, traceCall.Logs)

if isOneInchRFQTrade {
contractCall, err := decoder.Decode(OneinchMetaData.ABI, traceCall.Input)
Expand All @@ -115,15 +116,15 @@ func (p *Parser) recursiveDetectOneInchRFQTrades(tradeLog storage.TradeLog, trac
}

for _, subCall := range traceCall.Calls {
tradeLog, err = p.recursiveDetectOneInchRFQTrades(tradeLog, subCall, blockTimestamp)
tradeLog, err = p.recursiveDetectOneInchRFQTrades(tradeLog, log, subCall, blockTimestamp)
if err != nil {
return tradeLog, err
}
}
return tradeLog, nil
}

func (p *Parser) isOneInchRFQTrades(eventLogs []types.CallLog) bool {
func (p *Parser) isOneInchRFQTrades(originalLog ethereumTypes.Log, eventLogs []types.CallLog) bool {
for _, eventLog := range eventLogs {
if len(eventLog.Topics) == 0 {
continue
Expand All @@ -132,8 +133,36 @@ func (p *Parser) isOneInchRFQTrades(eventLogs []types.CallLog) bool {
if !strings.EqualFold(eventLog.Topics[0].String(), p.eventHash) {
continue
}

if !p.isSameEventLog(originalLog, eventLog) {
continue
}

return true
}

return false
}

// compares two event logs to determine the extract rfq order
// replaces by the log index in the future(if the debug_traceTransaction endpoint supports the log index)
func (p *Parser) isSameEventLog(originalLog ethereumTypes.Log, eventLog types.CallLog) bool {
// need to compare with the original log to get extract the order
if eventLog.Data != hexutil.Encode(originalLog.Data) || !strings.EqualFold(eventLog.Address.String(), eventLog.Address.String()) {
return false
}

isSameTopics := true
for idx, topic := range originalLog.Topics {
if len(eventLog.Topics) < idx {
isSameTopics = false
break
}
comparedTopic := eventLog.Topics[idx]
if topic.String() != comparedTopic.String() {
isSameTopics = false
break
}
}
return isSameTopics
}
18 changes: 16 additions & 2 deletions pkg/parser/oneinch/rfq_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"github.com/KyberNetwork/tradelogs/internal/types"
"github.com/KyberNetwork/tradelogs/pkg/storage"
"math/big"
)

const (
Expand Down Expand Up @@ -32,8 +33,21 @@ func ToTradeLog(tradeLog storage.TradeLog, contractCall *types.ContractCall) (st
tradeLog.MakerToken = rfqOrder.MakerAsset.String()
tradeLog.TakerToken = rfqOrder.TakerAsset.String()
tradeLog.Maker = rfqOrder.Maker.String()
tradeLog.MakerTokenAmount = rfqOrder.MakingAmount.String()
tradeLog.TakerTokenAmount = rfqOrder.TakingAmount.String()

// takerTokenAmount = (makingAmount * orderTakerAmount + orderMakerAmount - 1)/orderMakerAmount
orderMakerAmount := rfqOrder.MakingAmount
orderTakerAmount := rfqOrder.TakingAmount
makingAmount, ok := new(big.Int).SetString(tradeLog.MakerTokenAmount, 10)
if !ok {
return tradeLog, errors.New("failed to convert maker_token_amount")
}

takerTokenAmount := big.NewInt(0).Mul(makingAmount, orderTakerAmount)
takerTokenAmount = takerTokenAmount.Add(takerTokenAmount, orderMakerAmount)
takerTokenAmount = takerTokenAmount.Sub(takerTokenAmount, big.NewInt(1))
takerTokenAmount = takerTokenAmount.Div(takerTokenAmount, orderMakerAmount)

tradeLog.TakerTokenAmount = takerTokenAmount.String()
}

return tradeLog, nil
Expand Down

0 comments on commit 7c7aacb

Please sign in to comment.