Skip to content

Commit

Permalink
Merge pull request #536 from DefiantLabs/patch/poolmanager-swap-bugs
Browse files Browse the repository at this point in the history
patch/Update pool manager swap amount in parser to take into account cosmwa…
  • Loading branch information
pharr117 authored Mar 19, 2024
2 parents bf3f4e1 + 8e1cb0c commit 41474af
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 41474af

Please sign in to comment.