Skip to content

Commit

Permalink
Update pool manager swap amount in parser to take into account cosmwa…
Browse files Browse the repository at this point in the history
…sm swap executor that has final transfer entry not for sender
  • Loading branch information
pharr117 committed Mar 19, 2024
1 parent 6a35041 commit 8e1cb0c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 51 deletions.
60 changes: 39 additions & 21 deletions cosmos/modules/tx/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,34 +78,52 @@ func ParseTransferEvent(evt LogMessageEvent) ([]TransferEvent, error) {
return nil, errInvalidTransfer
}

for i := 0; i < len(evt.Attributes); i++ {
attrRecipient := evt.Attributes[i]
if attrRecipient.Key == "recipient" {
attrSenderIdx := i + 1
attrAmountIdx := i + 2
if attrAmountIdx < len(evt.Attributes) {
attrSender := evt.Attributes[attrSenderIdx]
attrAmount := evt.Attributes[attrAmountIdx]
if attrSender.Key == "sender" && attrAmount.Key == EventAttributeAmount {
transfers = append(transfers, TransferEvent{
Recipient: attrRecipient.Value,
Sender: attrSender.Value,
Amount: attrAmount.Value,
})
} else {
return nil, errInvalidTransfer
}
} else {
return nil, errInvalidTransfer
}
} else if i%3 == 0 { // every third attr should be "recipient"
if len(evt.Attributes)%3 != 0 {
return nil, errInvalidTransfer
}

// chunk the attributes into groups of 3
for i := 0; i < len(evt.Attributes); i += 3 {
transferEvent := TransferEvent{}
err := parseTransferAttributeIntoEvent(evt.Attributes[i], &transferEvent)
if err != nil {
return nil, err
}
err = parseTransferAttributeIntoEvent(evt.Attributes[i+1], &transferEvent)
if err != nil {
return nil, err
}
err = parseTransferAttributeIntoEvent(evt.Attributes[i+2], &transferEvent)
if err != nil {
return nil, err
}

// validate the transfer event
if transferEvent.Recipient == "" || transferEvent.Sender == "" || transferEvent.Amount == "" {
return nil, errInvalidTransfer
}

transfers = append(transfers, transferEvent)
}

return transfers, nil
}

func parseTransferAttributeIntoEvent(attr Attribute, evt *TransferEvent) error {
switch attr.Key {
case "recipient":
evt.Recipient = attr.Value
case "sender":
evt.Sender = attr.Value
case "amount":
evt.Amount = attr.Value
default:
return fmt.Errorf("unknown attribute %s", attr.Key)
}

return nil
}

// If order is reversed, the last attribute containing the given key will be returned
// otherwise the first attribute will be returned
func GetValueForAttribute(key string, evt *LogMessageEvent) (string, error) {
Expand Down
74 changes: 44 additions & 30 deletions osmosis/modules/poolmanager/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,42 +152,56 @@ func (sf *WrapperMsgSwapExactAmountIn) HandleMsg(msgType string, msg sdk.Msg, lo

transferEvents := txModule.GetEventsWithType("transfer", log)

var transferEvt *txModule.LogMessageEvent
if len(transferEvents) == 0 {
transferEvt = nil
} else {
transferEvt = &transferEvents[len(transferEvents)-1]
}

if !parsed && transferEvt != nil {
transferEvts, err := txModule.ParseTransferEvent(*transferEvt)
if err != nil {
return err
}
if !parsed && len(transferEvents) > 0 {

var parserError error
var lastParsedIndex int
// We will attempt to get the last transfer event that executed for the sender
// We are scoping it for now so as not to blast all the way to the beginning but to address
// poolmanager CosmWasm pool executions that seem to send some small amount to a different address right at the end
for i := len(transferEvents) - 1; !parsed && len(transferEvents)-2 >= 0 && i >= len(transferEvents)-2; i-- {
lastParsedIndex = i
transferEvt := &transferEvents[i]

transferEvts, err := txModule.ParseTransferEvent(*transferEvt)
if err != nil {
parserError = err
continue
}

// The last transfer event should contain the final transfer to the sender
lastTransferEvt := transferEvts[len(transferEvts)-1]

if lastTransferEvt.Recipient != sf.Address {
parserError = errors.New("transfer event recipient does not match message sender")
continue
}

tokenOut, err := sdk.ParseCoinNormalized(lastTransferEvt.Amount)
if err != nil {
parserError = err
continue
}

// The last route in the hops gives the token out denom and pool ID for the final output
lastRoute := sf.OsmosisMsgSwapExactAmountIn.Routes[len(sf.OsmosisMsgSwapExactAmountIn.Routes)-1]
lastRouteDenom := lastRoute.TokenOutDenom

if tokenOut.Denom != lastRouteDenom {
parserError = errors.New("final transfer denom does not match last route denom")
continue
}

// The last transfer event should contain the final transfer to the sender
lastTransferEvt := transferEvts[len(transferEvts)-1]

if lastTransferEvt.Recipient != sf.Address {
return errors.New("transfer event recipient does not match message sender")
}
sf.TokenOut = tokenOut

tokenOut, err := sdk.ParseCoinNormalized(lastTransferEvt.Amount)
if err != nil {
return err
parsed = true
parserError = nil
}

// The last route in the hops gives the token out denom and pool ID for the final output
lastRoute := sf.OsmosisMsgSwapExactAmountIn.Routes[len(sf.OsmosisMsgSwapExactAmountIn.Routes)-1]
lastRouteDenom := lastRoute.TokenOutDenom

if tokenOut.Denom != lastRouteDenom {
return errors.New("final transfer denom does not match last route denom")
if parserError != nil {
return fmt.Errorf("error parsing transfer event. Last processed index (%d): %s", lastParsedIndex, parserError)
}

sf.TokenOut = tokenOut

parsed = true
}

if !parsed {
Expand Down

0 comments on commit 8e1cb0c

Please sign in to comment.