diff --git a/.vscode/launch.json b/.vscode/launch.json index 4845b192a4b..c6347cb24fe 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -283,12 +283,12 @@ "type": "go", "request": "launch", "mode": "test", - "program": "${workspaceFolder}/x/txfees", + "program": "${workspaceFolder}/x/txfees/keeper/txfee_filters", "args": [ "-test.timeout", "30m", "-test.run", - "TestKeeperTestSuite/TestYourName", + "TestTxFeeFilter/TestIsArbTxLooseAuthz_SwapMsg", "-test.v" ], }, diff --git a/x/txfees/keeper/txfee_filters/arb_tx.go b/x/txfees/keeper/txfee_filters/arb_tx.go index 00928422e70..07babba4478 100644 --- a/x/txfees/keeper/txfee_filters/arb_tx.go +++ b/x/txfees/keeper/txfee_filters/arb_tx.go @@ -26,6 +26,25 @@ type AffiliateSwapMsg struct { Swap `json:"swap"` } +type InputCoin struct { + Denom string `json:"denom"` + Amount string `json:"amount"` +} + +type Slippage struct { + MinOutputAmount string `json:"min_output_amount"` +} + +type ContractSwap struct { + InputCoin InputCoin `json:"input_coin"` + OutputDenom string `json:"output_denom"` + Slippage Slippage `json:"slippage"` +} + +type ContractSwapMsg struct { + ContractSwap `json:"swap"` +} + // TokenDenomsOnPath implements types.SwapMsgRoute. func (m AffiliateSwapMsg) TokenDenomsOnPath() []string { denoms := make([]string, 0, len(m.Routes)+1) @@ -108,6 +127,15 @@ func isArbTxLooseAuthz(msg sdk.Msg, swapInDenom string, lpTypesSeen map[gammtype // Check that the contract message is an affiliate swap message if ok := isAffiliateSwapMsg(contractMessage); !ok { + + if ok := isSwapContractMsg(contractMessage); !ok { + return swapInDenom, false + } + + return swapInDenom, false + } + + if ok := isSwapContractMsg(contractMessage); !ok { return swapInDenom, false } @@ -195,3 +223,33 @@ func isAffiliateSwapMsg(msg []byte) bool { return true } + +type Coin struct { + Denom string `json:"denom"` + Amount string `json:"amount"` +} + +func isSwapContractMsg(msg []byte) bool { + // Check that the contract message is a valid JSON object + jsonObject := make(map[string]interface{}) + err := json.Unmarshal(msg, &jsonObject) + if err != nil { + return false + } + + // check the main key is "swap" + swap, ok := jsonObject["swap"].(map[string]interface{}) + if !ok { + return false + } + + if routes, ok := swap["input_coin"].([]interface{}); !ok || len(routes) == 0 { + return false + } + + if tokenOutMinAmount, ok := swap["output_denom"].(map[string]interface{}); !ok || len(tokenOutMinAmount) == 0 { + return false + } + + return true +} diff --git a/x/txfees/keeper/txfee_filters/arb_tx_test.go b/x/txfees/keeper/txfee_filters/arb_tx_test.go index 1c7f24e822a..4268944b702 100644 --- a/x/txfees/keeper/txfee_filters/arb_tx_test.go +++ b/x/txfees/keeper/txfee_filters/arb_tx_test.go @@ -65,6 +65,36 @@ func (suite *KeeperTestSuite) TestIsArbTxLooseAuthz_AffiliateSwapMsg() { suite.Require().True(isArb) } +// Tests that the arb filter is enabled on swap msg. +func (suite *KeeperTestSuite) TestIsArbTxLooseAuthz_SwapMsg() { + contractSwapMsg := &txfee_filters.ContractSwapMsg{ + ContractSwap: txfee_filters.ContractSwap{ + InputCoin: txfee_filters.InputCoin{ + Amount: "2775854", + Denom: "ibc/D1542AA8762DB13087D8364F3EA6509FD6F009A34F00426AF9E4F9FA85CBBF1F", + }, + OutputDenom: "ibc/D1542AA8762DB13087D8364F3EA6509FD6F009A34F00426AF9E4F9FA85CBBF1F", + Slippage: txfee_filters.Slippage{ + MinOutputAmount: "2775854", + }, + }, + } + + msgBz, err := json.Marshal(contractSwapMsg) + suite.Require().NoError(err) + + // https://celatone.osmosis.zone/osmosis-1/txs/8D20755D4E009CB72C763963A76886BCCCC5C2EBFC3F57266332710216A0D10D + executeMsg := &wasmtypes.MsgExecuteContract{ + Contract: "osmo1etpha3a65tds0hmn3wfjeag6wgxgrkuwg2zh94cf5hapz7mz04dq6c25s5", + Sender: "osmo1dldrxz5p8uezxz3qstpv92de7wgfp7hvr72dcm", + Funds: sdk.NewCoins(sdk.NewCoin("ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4", sdk.NewInt(217084399))), + Msg: msgBz, + } + + _, isArb := txfee_filters.IsArbTxLooseAuthz(executeMsg, executeMsg.Funds[0].Denom, map[types.LiquidityChangeType]bool{}) + suite.Require().True(isArb) +} + func (suite *KeeperTestSuite) TestIsArbTxLooseAuthz_OtherMsg() { otherMsg := []byte(`{"update_feed": {}}`)