-
Notifications
You must be signed in to change notification settings - Fork 609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cleanup/Optimize gas for swaps #5850
Conversation
// } | ||
|
||
// Send the input token from the user to the pool's primary address | ||
err := k.bankKeeper.SendCoins(ctx, swapDetails.Sender, pool.GetAddress(), sdk.Coins{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: i tried using multisend api to replace multiple sendCoins call, but the keeper function doesnot take multiple input address
ref: https://github.com/osmosis-labs/cosmos-sdk/blob/osmosis-main/x/bank/types/msgs.go#L174-L175
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we will want to still do multiple multi-sends, just only one send per sender!
2324df2
to
da0d51e
Compare
x/concentrated-liquidity/swaps.go
Outdated
// Send the output token to the sender from the pool | ||
err = k.bankKeeper.SendCoins(ctx, pool.GetAddress(), swapDetails.Sender, sdk.Coins{ | ||
swapDetails.TokenOut, | ||
}) | ||
err = k.bankKeeper.InputOutputCoins(ctx, []banktypes.Input{{ | ||
Address: pool.GetAddress().String(), | ||
Coins: sdk.NewCoins(swapDetails.TokenOut), | ||
}}, []banktypes.Output{ | ||
{ | ||
Address: swapDetails.Sender.String(), | ||
Coins: sdk.NewCoins(swapDetails.TokenOut), | ||
}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the benefit of using multi-send API when we replace each regular API with a multi-send one?
I would assume that we would want to batch all inputs and all outputs and run a single multi-send API at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea i think so, using InputOutputCoins made gas slightly lower. ref: https://github.com/osmosis-labs/osmosis/pull/5850/files#r1266377932
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change here isn't quite what I had in mind. I was expecting to be doing a MultiSend (not an InputOutputCoins!) and combining the two sends from the sender! My bad, I forgot that MultiSend is the name of the SDK message, which doesn't actually use the sendManyCoins API.
https://github.com/osmosis-labs/cosmos-sdk/blob/osmosis-main/x/bank/keeper/send.go#L21C7-L21C7
This will eliminate the repeated-get & write for the sender
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though your change suggests an interesting idea, thats actually better than mine.
We could do all the sends here as a single InputOutputCoins call! That will give us a minimal number of I/O ops
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still does not make sense to me, this still looks like three separate bank sends to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InputOutputCoins
is VERY optimal when there is 1inputSender and ManyOutputReciever because all inputs and outputs gets handled into one single operation.
however, we cannot do that in our case because we have different inputs and different outputs. I wanted to revert back to SendCoins
because it is simpler however, i saw that Input/OutputCoins was slightly gas efficient (https://github.com/osmosis-labs/osmosis/pull/5850/files/46ad00d4e066c02ce9fa6e2775a45c41898bd58e#r1266377932)
// Make a large swap in InGivenOut (negative tick direction) from currentTick = 1735 to 736 | ||
// Amount of tickCrossed = 998 | ||
// Make sure the gas is < 50M | ||
_, _, _, err = s.clk.SwapInAmtGivenOut(s.Ctx, swapAddress, pool, sdk.NewCoin(USDC, sdk.NewInt(50_000_000_000)), ETH, pool.GetSpreadFactor(s.Ctx), sdk.ZeroDec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ref:
swapGasAmount(sendCoins): 22_367_874
swapGasAmount(InputOutputCoins): 22_345_380
This is state breaking and can't be backported due to affecting gas. |
Can you add a changelog for improving gas of CL swaps? |
added changelog |
pool, err := s.clk.GetPoolById(s.Ctx, pool.GetId()) | ||
s.Require().NoError(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed in place of the pool object that is provided in the args? No state change occurs prior to this call on the pool obj as far as I see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So pool obj change when we create first position. It updates the current Sqr Price https://github.com/osmosis-labs/osmosis/blob/main/x/concentrated-liquidity/lp.go#L476
x/concentrated-liquidity/swaps.go
Outdated
// Send the output token to the sender from the pool | ||
err = k.bankKeeper.SendCoins(ctx, pool.GetAddress(), swapDetails.Sender, sdk.Coins{ | ||
swapDetails.TokenOut, | ||
}) | ||
err = k.bankKeeper.InputOutputCoins(ctx, []banktypes.Input{{ | ||
Address: pool.GetAddress().String(), | ||
Coins: sdk.NewCoins(swapDetails.TokenOut), | ||
}}, []banktypes.Output{ | ||
{ | ||
Address: swapDetails.Sender.String(), | ||
Coins: sdk.NewCoins(swapDetails.TokenOut), | ||
}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still does not make sense to me, this still looks like three separate bank sends to me.
8247513
to
5a74192
Compare
okay just tried to refactor and there was lots of unintended behaviors in core swap logic around state get/set. So will probably close this PR to not break the current flow |
Closes: #5842
What is the purpose of the change
Theres one trivial extra GetPool call we can eliminate from all swaps by making compute swap methods take in a pool instead of poolID
I think its maybe two GetPools eliminatable, including the one in updatePoolForSwap? This one not as clear
Similarly we can use the multi-send api's from bank to optimize the final fund transfers
Testing and Verifying
tested on localosmosis by performing swap and comparing outputs
Documentation and Release Note
Unreleased
section ofCHANGELOG.md
?Where is the change documented?
x/{module}/README.md
)