Skip to content

Commit

Permalink
phase 2 - misc proto renaming (#992)
Browse files Browse the repository at this point in the history
  • Loading branch information
sampocs authored Nov 28, 2023
1 parent d4f4fa6 commit b32af28
Show file tree
Hide file tree
Showing 13 changed files with 349 additions and 297 deletions.
16 changes: 7 additions & 9 deletions proto/stride/stakeibc/trade_route.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package stride.stakeibc;
import "gogoproto/gogo.proto";
import "stride/stakeibc/ica_account.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/Stride-Labs/stride/v16/x/stakeibc/types";

Expand All @@ -30,9 +29,9 @@ message TradeRoute {
// ibc denom of the reward on the trade chain, input to the swap
string reward_denom_on_trade_zone = 3;
// ibc of the host denom on the trade chain, output from the swap
string target_denom_on_trade_zone = 4;
string host_denom_on_trade_zone = 4;
// should be the same as the native host denom on the host chain
string target_denom_on_host_zone = 5;
string host_denom_on_host_zone = 5;

TradeHop host_to_reward_hop = 6 [ (gogoproto.nullable) = false ];
TradeHop reward_to_trade_hop = 7 [ (gogoproto.nullable) = false ];
Expand All @@ -49,14 +48,13 @@ message TradeRoute {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// timestamp that the price was last updated
google.protobuf.Timestamp price_update_time = 11
[ (gogoproto.nullable) = false, (gogoproto.stdtime) = true ];
// unix time in seconds that the price was last updated
uint64 price_update_timestamp = 11;

// Threshold defining the percentage of tokens that could be lost in the trade
// This captures both the loss from slippage and from a stale price value on
// stride 0.05 means the output from the trade can be no less than a 5%
// deviation from the current value
// This captures both the loss from slippage and from a stale price on stride
// 0.05 means the output from the trade can be no less than a 5% deviation
// from the current value
string max_allowed_swap_loss_rate = 12 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
Expand Down
10 changes: 8 additions & 2 deletions proto/stride/stakeibc/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,15 @@ message MsgCreateTradeRoute {
// The osmosis pool ID
uint64 pool_id = 13;

// Threshold defining the percentage of tokens that could be lost in the trade
// This captures both the loss from slippage and from a stale price on stride
// "0.05" means the output from the trade can be no less than a 5% deviation
// from the current value
string max_allowed_swap_loss_rate = 14;

// min and max set boundaries of reward denom on trade chain we will swap
uint64 min_swap_amount = 14;
uint64 max_swap_amount = 15;
uint64 min_swap_amount = 15;
uint64 max_swap_amount = 16;
}
message MsgCreateTradeRouteResponse {}

Expand Down
17 changes: 8 additions & 9 deletions x/stakeibc/keeper/icqcallbacks_pool_price.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ import (
// P0LastSpotPrice gives the ratio of Asset0Denom / Asset1Denom
// P1LastSpotPrice gives the ratio of Asset1Denom / Asset0Denom
//
// When storing down the price, we want to denominate the price of the TargetDenom,
// relative to the price of the RewardDenom, which means we have to take the inverse
// from the response
// When storing down the price, we want to store down the ratio of HostDenom.
// Meaning, if Asset0Denom is the host denom, we want to store P0LastSpotPrice
func PoolPriceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Query) error {
k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(query.ChainId, ICQCallbackID_PoolPrice,
"Starting pool spot price callback, QueryId: %vs, QueryType: %s, Connection: %s", query.Id, query.QueryType, query.ConnectionId))
Expand Down Expand Up @@ -55,19 +54,19 @@ func PoolPriceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Qu
// Get the associate "SpotPrice" from the twap record, based on the asset ordering
// The "SpotPrice" is actually a ratio of the assets in the pool
var price sdk.Dec
if twapRecord.Asset0Denom == tradeRoute.TargetDenomOnTradeZone {
if twapRecord.Asset0Denom == tradeRoute.HostDenomOnTradeZone {
price = twapRecord.P0LastSpotPrice
} else {
price = twapRecord.P1LastSpotPrice
}

k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_PoolPrice,
"Query response - price ratio of %s to %s is %s",
tradeRoute.RewardDenomOnTradeZone, tradeRoute.TargetDenomOnTradeZone, price))
tradeRoute.RewardDenomOnTradeZone, tradeRoute.HostDenomOnTradeZone, price))

// Update the price and time on the trade route data
tradeRoute.SwapPrice = price
tradeRoute.PriceUpdateTime = ctx.BlockTime()
tradeRoute.PriceUpdateTimestamp = uint64(ctx.BlockTime().UnixNano())
k.SetTradeRoute(ctx, tradeRoute)

return nil
Expand All @@ -76,16 +75,16 @@ func PoolPriceCallback(k Keeper, ctx sdk.Context, args []byte, query icqtypes.Qu
// Helper function to confirm that the two assets in the twap record match the assets in the trade route
// The assets in the twap record are sorted alphabetically, so we have to check both orderings
func AssertTwapAssetsMatchTradeRoute(twapRecord types.OsmosisTwapRecord, tradeRoute types.TradeRoute) error {
hostDenomMatchFirst := twapRecord.Asset0Denom == tradeRoute.TargetDenomOnTradeZone
hostDenomMatchFirst := twapRecord.Asset0Denom == tradeRoute.HostDenomOnTradeZone
rewardDenomMatchSecond := twapRecord.Asset1Denom == tradeRoute.RewardDenomOnTradeZone

rewardDenomMatchFirst := twapRecord.Asset0Denom == tradeRoute.RewardDenomOnTradeZone
hostDenomMatchSecond := twapRecord.Asset1Denom == tradeRoute.TargetDenomOnTradeZone
hostDenomMatchSecond := twapRecord.Asset1Denom == tradeRoute.HostDenomOnTradeZone

if (hostDenomMatchFirst && rewardDenomMatchSecond) || (rewardDenomMatchFirst && hostDenomMatchSecond) {
return nil
}

return fmt.Errorf("Assets in query response (%s, %s) do not match denom's from trade route (%s, %s)",
twapRecord.Asset0Denom, twapRecord.Asset1Denom, tradeRoute.TargetDenomOnTradeZone, tradeRoute.RewardDenomOnTradeZone)
twapRecord.Asset0Denom, twapRecord.Asset1Denom, tradeRoute.HostDenomOnTradeZone, tradeRoute.RewardDenomOnTradeZone)
}
2 changes: 1 addition & 1 deletion x/stakeibc/keeper/icqcallbacks_trade_converted_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TradeConvertedBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query

k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeConvertedBalance,
"Sending discovered converted tokens %v %s from tradeZone back to hostZone",
tradeConvertedBalanceAmount, tradeRoute.TargetDenomOnTradeZone))
tradeConvertedBalanceAmount, tradeRoute.HostDenomOnTradeZone))

return nil
}
4 changes: 2 additions & 2 deletions x/stakeibc/keeper/icqcallbacks_trade_reward_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TradeRewardBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query ic

// Trade all found reward tokens in the trade ICA to the output denom of their trade pool
err = utils.ApplyFuncIfNoError(ctx, func(c sdk.Context) error {
return k.TradeRewardTokens(ctx, tradeRewardBalanceAmount, tradeRoute)
return k.SwapRewardTokens(ctx, tradeRewardBalanceAmount, tradeRoute)
})
if err != nil {
k.Logger(ctx).Error(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeRewardBalance,
Expand All @@ -57,7 +57,7 @@ func TradeRewardBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query ic

k.Logger(ctx).Info(utils.LogICQCallbackWithHostZone(chainId, ICQCallbackID_TradeRewardBalance,
"Swapping discovered reward tokens %v %s for %s",
tradeRewardBalanceAmount, tradeRoute.RewardDenomOnTradeZone, tradeRoute.TargetDenomOnTradeZone))
tradeRewardBalanceAmount, tradeRoute.RewardDenomOnTradeZone, tradeRoute.HostDenomOnTradeZone))

return nil
}
30 changes: 21 additions & 9 deletions x/stakeibc/keeper/msg_server_create_trade_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
)

var DefaultMaxAllowedSwapLossRate = "0.05"

// Gov tx to to register a trade route that swaps reward tokens for a different denom
//
// Example proposal:
Expand Down Expand Up @@ -107,20 +109,30 @@ func (ms msgServer) CreateTradeRoute(goCtx context.Context, msg *types.MsgCreate
ToAccount: hostICA,
}

maxAllowedSwapLossRate := msg.MaxAllowedSwapLossRate
if maxAllowedSwapLossRate == "" {
maxAllowedSwapLossRate = DefaultMaxAllowedSwapLossRate
}

// Finally build and store the main trade route
tradeRoute := types.TradeRoute{
RewardDenomOnHostZone: msg.RewardDenomOnHost,
RewardDenomOnRewardZone: msg.RewardDenomOnReward,
RewardDenomOnTradeZone: msg.RewardDenomOnTrade,
TargetDenomOnTradeZone: msg.HostDenomOnTrade,
TargetDenomOnHostZone: msg.HostDenomOnHost,
HostToRewardHop: hostToRewardHop,
RewardToTradeHop: rewardToTradeHop,
TradeToHostHop: tradeToHostHop,
PoolId: msg.PoolId,
SwapPrice: sdk.ZeroDec(), // this should only ever be set by ICQ so initialize to blank
MinSwapAmount: sdkmath.NewIntFromUint64(msg.MinSwapAmount),
MaxSwapAmount: sdkmath.NewIntFromUint64(msg.MaxSwapAmount),
HostDenomOnTradeZone: msg.HostDenomOnTrade,
HostDenomOnHostZone: msg.HostDenomOnHost,

HostToRewardHop: hostToRewardHop,
RewardToTradeHop: rewardToTradeHop,
TradeToHostHop: tradeToHostHop,

PoolId: msg.PoolId,
SwapPrice: sdk.ZeroDec(), // this should only ever be set by ICQ so initialize to blank
PriceUpdateTimestamp: 0,

MaxAllowedSwapLossRate: sdk.MustNewDecFromStr(maxAllowedSwapLossRate),
MinSwapAmount: sdkmath.NewIntFromUint64(msg.MinSwapAmount),
MaxSwapAmount: sdkmath.NewIntFromUint64(msg.MaxSwapAmount),
}

ms.Keeper.SetTradeRoute(ctx, tradeRoute)
Expand Down
4 changes: 2 additions & 2 deletions x/stakeibc/keeper/msg_server_delete_trade_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func (k msgServer) DeleteTradeRoute(goCtx context.Context, msg *types.MsgDeleteT

routes := k.GetAllTradeRoutes(ctx)
for _, route := range routes {
if route.TargetDenomOnHostZone == msg.HostDenom && route.RewardDenomOnRewardZone == msg.RewardDenom {
k.RemoveTradeRoute(ctx, route.RewardDenomOnHostZone, route.TargetDenomOnHostZone)
if route.HostDenomOnHostZone == msg.HostDenom && route.RewardDenomOnRewardZone == msg.RewardDenom {
k.RemoveTradeRoute(ctx, route.RewardDenomOnHostZone, route.HostDenomOnHostZone)
}
// if no matching trade route was found for the given host-denom and reward-denom... do nothing
}
Expand Down
2 changes: 1 addition & 1 deletion x/stakeibc/keeper/msg_server_update_trade_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (k msgServer) UpdateTradeRoute(goCtx context.Context, msg *types.MsgUpdateT

routes := k.GetAllTradeRoutes(ctx)
for _, route := range routes {
if route.TargetDenomOnHostZone == msg.HostDenom && route.RewardDenomOnRewardZone == msg.RewardDenom {
if route.HostDenomOnHostZone == msg.HostDenom && route.RewardDenomOnRewardZone == msg.RewardDenom {
route.PoolId = msg.PoolId
route.MinSwapAmount = msg.MinSwapAmount
route.MaxSwapAmount = msg.MaxSwapAmount
Expand Down
26 changes: 13 additions & 13 deletions x/stakeibc/keeper/reward_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ import (
// 1. Epochly check the reward denom balance in the withdrawal address
// on callback, send all this reward denom from withdrawl ICA to trade ICA on the trade zone (OSMOSIS)
// 2. Epochly check the reward denom balance in trade ICA
// on callback, trade all reward denom for target output denom defined by pool and routes in params
// 3. Epochly check the target denom balance in trade ICA
// on callback, transfer these target denoms from trade ICA to withdrawal ICA on original host zone
// on callback, trade all reward denom for host denom defined by pool and routes in params
// 3. Epochly check the host denom balance in trade ICA
// on callback, transfer these host denom tokens from trade ICA to withdrawal ICA on original host zone
//
// Normal staking flow continues from there. So if the target denom is the original host zone base denom
// as will often be the case, then these tokens will follow the normal staking and distribution flow.
// Normal staking flow continues from there. So the host denom tokens will land on the original host zone
// and the normal staking and distribution flow will continue from there.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ICA tx will kick off transfering the reward tokens from the hostZone withdrawl ICA to the tradeZone trade ICA
Expand Down Expand Up @@ -106,7 +106,7 @@ func (k Keeper) TransferConvertedTokensTradeToHost(ctx sdk.Context, amount sdkma
}
timeout := uint64(strideEpochTracker.NextEpochStartTime)

convertedDenom := route.TargetDenomOnTradeZone
convertedDenom := route.HostDenomOnTradeZone
sendTokens := sdk.NewCoin(convertedDenom, amount)

tradeIcaAddress := route.TradeToHostHop.FromAccount.Address
Expand Down Expand Up @@ -138,10 +138,10 @@ func (k Keeper) TransferConvertedTokensTradeToHost(ctx sdk.Context, amount sdkma
return nil
}

// Trade reward tokens in the Trade ICA for the target output token type using ICA remote tx on trade zone
// Trade reward tokens in the Trade ICA for the host denom tokens using ICA remote tx on trade zone
// The amount represents the total amount of the reward token in the trade ICA found by the calling ICQ
// Depending on min and max swap amounts set in the route, it is possible not the full amount given will swap
func (k Keeper) TradeRewardTokens(ctx sdk.Context, rewardAmount sdkmath.Int, route types.TradeRoute) error {
func (k Keeper) SwapRewardTokens(ctx sdk.Context, rewardAmount sdkmath.Int, route types.TradeRoute) error {
// If the min swap amount was not set it would be ZeroInt, if positive we need to compare to the amount given
// then if the min swap amount is greater than the current amount, do nothing this epoch to avoid small swaps
if route.MinSwapAmount.IsPositive() && route.MinSwapAmount.GT(rewardAmount) {
Expand All @@ -162,7 +162,7 @@ func (k Keeper) TradeRewardTokens(ctx sdk.Context, rewardAmount sdkmath.Int, rou
}

// If there is a valid price, use it to set a floor for the acceptable minimum output tokens
// minOut is the minimum number of route.TargetDenomOnTradeZone we must receive or the swap will fail
// minOut is the minimum number of HostDenom tokens we must receive or the swap will fail
//
// To calculate minOut, we first convert the rewardAmount into units of HostDenom,
// and then we multiply by (1 - MaxAllowedSwapLossRate)
Expand All @@ -183,7 +183,7 @@ func (k Keeper) TradeRewardTokens(ctx sdk.Context, rewardAmount sdkmath.Int, rou
// decide which msg generation function to call based on check of which tradeZone was passed in
routes := []types.SwapAmountInRoute{{
PoolId: route.PoolId,
TokenOutDenom: route.TargetDenomOnTradeZone,
TokenOutDenom: route.HostDenomOnTradeZone,
}}
msgs := []proto.Message{&types.MsgSwapExactAmountIn{
Sender: tradeIcaAccount.Address,
Expand Down Expand Up @@ -323,7 +323,7 @@ func (k Keeper) TradeConvertedBalanceQuery(ctx sdk.Context, route types.TradeRou
if err != nil {
return errorsmod.Wrapf(err, "invalid trade account address (%s), could not decode", tradeAccount.Address)
}
queryData := append(bankTypes.CreateAccountBalancesPrefix(tradeAddressBz), []byte(route.TargetDenomOnTradeZone)...)
queryData := append(bankTypes.CreateAccountBalancesPrefix(tradeAddressBz), []byte(route.HostDenomOnTradeZone)...)

// Timeout query at end of epoch
strideEpochTracker, found := k.GetEpochTracker(ctx, epochstypes.STRIDE_EPOCH)
Expand Down Expand Up @@ -366,7 +366,7 @@ func (k Keeper) PoolPriceQuery(ctx sdk.Context, route types.TradeRoute) error {
k.Logger(ctx).Info(utils.LogWithHostZone(tradeAccount.ChainId, "Submitting ICQ for spot price in this pool"))

// Sort denom's
denom1, denom2 := route.RewardDenomOnTradeZone, route.TargetDenomOnTradeZone
denom1, denom2 := route.RewardDenomOnTradeZone, route.HostDenomOnTradeZone
if denom1 > denom2 {
denom1, denom2 = denom2, denom1
}
Expand Down Expand Up @@ -446,7 +446,7 @@ func (k Keeper) SwapAllRewardTokens(ctx sdk.Context) {

// Helper function to be run hourly, kicks off query to get and update the swap price in keeper data
func (k Keeper) UpdateAllSwapPrices(ctx sdk.Context) {
k.SetTradeRoute(ctx, types.TradeRoute{RewardDenomOnHostZone: "A", TargetDenomOnHostZone: "B"})
k.SetTradeRoute(ctx, types.TradeRoute{RewardDenomOnHostZone: "A", HostDenomOnHostZone: "B"})
for _, route := range k.GetAllTradeRoutes(ctx) {
// ICQ swap price for the specific pair on this route and update keeper on callback
if err := k.PoolPriceQuery(ctx, route); err != nil {
Expand Down
14 changes: 7 additions & 7 deletions x/stakeibc/keeper/trade_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ func (s *KeeperTestSuite) CreateTradeRoutes() (routes []types.TradeRoute) {
RewardDenomOnHostZone: "ibc-" + rewardDenom + "-on-" + hostChain,
RewardDenomOnRewardZone: rewardDenom,
RewardDenomOnTradeZone: "ibc-" + rewardDenom + "-on-" + tradeChain,
TargetDenomOnTradeZone: "ibc-" + hostDenom + "-on-" + tradeChain,
TargetDenomOnHostZone: hostDenom,
HostDenomOnTradeZone: "ibc-" + hostDenom + "-on-" + tradeChain,
HostDenomOnHostZone: hostDenom,

HostToRewardHop: hostRewardHop,
RewardToTradeHop: rewardTradeHop,
TradeToHostHop: tradeHostHop,

PoolId: uint64(i * 100),
SwapPrice: sdk.OneDec(),
PoolId: uint64(i * 100),
SwapPrice: sdk.OneDec(),

MinSwapAmount: sdk.ZeroInt(),
MaxSwapAmount: sdk.NewInt(1_000_000_000),
Expand All @@ -72,7 +72,7 @@ func (s *KeeperTestSuite) TestGetTradeRoute() {
routes := s.CreateTradeRoutes()
for i, route := range routes {
startDenom := route.RewardDenomOnHostZone
endDenom := route.TargetDenomOnHostZone
endDenom := route.HostDenomOnHostZone

actualRoute, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, startDenom, endDenom)
s.Require().True(found, "route should have been found")
Expand All @@ -83,8 +83,8 @@ func (s *KeeperTestSuite) TestGetTradeRoute() {
func (s *KeeperTestSuite) TestRemoveTradeRoute() {
routes := s.CreateTradeRoutes()
for _, route := range routes {
s.App.StakeibcKeeper.RemoveTradeRoute(s.Ctx, route.RewardDenomOnHostZone, route.TargetDenomOnHostZone)
_, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, route.RewardDenomOnHostZone, route.TargetDenomOnHostZone)
s.App.StakeibcKeeper.RemoveTradeRoute(s.Ctx, route.RewardDenomOnHostZone, route.HostDenomOnHostZone)
_, found := s.App.StakeibcKeeper.GetTradeRoute(s.Ctx, route.RewardDenomOnHostZone, route.HostDenomOnHostZone)
s.Require().False(found, "route should not have been found")
}
}
Expand Down
2 changes: 1 addition & 1 deletion x/stakeibc/types/trade_route.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package types

func (t TradeRoute) GetKey() []byte {
return TradeRouteKeyFromDenoms(t.RewardDenomOnHostZone, t.TargetDenomOnHostZone)
return TradeRouteKeyFromDenoms(t.RewardDenomOnHostZone, t.HostDenomOnHostZone)
}
Loading

0 comments on commit b32af28

Please sign in to comment.