From ebf8fe427803a2a13c51e4c2a4146e88a42b6cce Mon Sep 17 00:00:00 2001 From: Tian Date: Mon, 23 Sep 2024 14:58:43 -0400 Subject: [PATCH 01/10] add megavault withdrawal info query (#2316) --- .../codegen/dydxprotocol/vault/query.lcd.ts | 18 +- .../dydxprotocol/vault/query.rpc.Query.ts | 16 +- .../src/codegen/dydxprotocol/vault/query.ts | 186 ++++- proto/dydxprotocol/vault/query.proto | 38 + protocol/x/vault/client/cli/query.go | 36 + .../keeper/grpc_query_withdrawal_info.go | 40 ++ .../keeper/grpc_query_withdrawal_info_test.go | 236 ++++++ protocol/x/vault/keeper/withdraw.go | 328 ++++++--- protocol/x/vault/types/query.pb.go | 669 ++++++++++++++++-- protocol/x/vault/types/query.pb.gw.go | 83 +++ 10 files changed, 1469 insertions(+), 181 deletions(-) create mode 100644 protocol/x/vault/keeper/grpc_query_withdrawal_info.go create mode 100644 protocol/x/vault/keeper/grpc_query_withdrawal_info_test.go diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts index d816987fff..9350c68ecf 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts @@ -1,6 +1,6 @@ import { setPaginationParams } from "../../helpers"; import { LCDClient } from "@osmonauts/lcd"; -import { QueryParamsRequest, QueryParamsResponseSDKType, QueryVaultRequest, QueryVaultResponseSDKType, QueryAllVaultsRequest, QueryAllVaultsResponseSDKType, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponseSDKType, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponseSDKType, QueryVaultParamsRequest, QueryVaultParamsResponseSDKType } from "./query"; +import { QueryParamsRequest, QueryParamsResponseSDKType, QueryVaultRequest, QueryVaultResponseSDKType, QueryAllVaultsRequest, QueryAllVaultsResponseSDKType, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponseSDKType, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponseSDKType, QueryVaultParamsRequest, QueryVaultParamsResponseSDKType, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponseSDKType } from "./query"; export class LCDQueryClient { req: LCDClient; @@ -16,6 +16,7 @@ export class LCDQueryClient { this.megavaultTotalShares = this.megavaultTotalShares.bind(this); this.megavaultOwnerShares = this.megavaultOwnerShares.bind(this); this.vaultParams = this.vaultParams.bind(this); + this.megavaultWithdrawalInfo = this.megavaultWithdrawalInfo.bind(this); } /* Queries the Params. */ @@ -79,5 +80,20 @@ export class LCDQueryClient { const endpoint = `dydxprotocol/vault/params/${params.type}/${params.number}`; return await this.req.get(endpoint); } + /* Queries withdrawal info for megavault. */ + + + async megavaultWithdrawalInfo(params: QueryMegavaultWithdrawalInfoRequest): Promise { + const options: any = { + params: {} + }; + + if (typeof params?.sharesToWithdraw !== "undefined") { + options.params.shares_to_withdraw = params.sharesToWithdraw; + } + + const endpoint = `dydxprotocol/vault/megavault/withdrawal_info`; + return await this.req.get(endpoint, options); + } } \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts index c170958b7d..a77656dc6c 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts @@ -1,7 +1,7 @@ import { Rpc } from "../../helpers"; import * as _m0 from "protobufjs/minimal"; import { QueryClient, createProtobufRpcClient } from "@cosmjs/stargate"; -import { QueryParamsRequest, QueryParamsResponse, QueryVaultRequest, QueryVaultResponse, QueryAllVaultsRequest, QueryAllVaultsResponse, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponse, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponse, QueryVaultParamsRequest, QueryVaultParamsResponse } from "./query"; +import { QueryParamsRequest, QueryParamsResponse, QueryVaultRequest, QueryVaultResponse, QueryAllVaultsRequest, QueryAllVaultsResponse, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponse, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponse, QueryVaultParamsRequest, QueryVaultParamsResponse, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponse } from "./query"; /** Query defines the gRPC querier service. */ export interface Query { @@ -22,6 +22,9 @@ export interface Query { /** Queries vault params of a vault. */ vaultParams(request: QueryVaultParamsRequest): Promise; + /** Queries withdrawal info for megavault. */ + + megavaultWithdrawalInfo(request: QueryMegavaultWithdrawalInfoRequest): Promise; } export class QueryClientImpl implements Query { private readonly rpc: Rpc; @@ -34,6 +37,7 @@ export class QueryClientImpl implements Query { this.megavaultTotalShares = this.megavaultTotalShares.bind(this); this.megavaultOwnerShares = this.megavaultOwnerShares.bind(this); this.vaultParams = this.vaultParams.bind(this); + this.megavaultWithdrawalInfo = this.megavaultWithdrawalInfo.bind(this); } params(request: QueryParamsRequest = {}): Promise { @@ -76,6 +80,12 @@ export class QueryClientImpl implements Query { return promise.then(data => QueryVaultParamsResponse.decode(new _m0.Reader(data))); } + megavaultWithdrawalInfo(request: QueryMegavaultWithdrawalInfoRequest): Promise { + const data = QueryMegavaultWithdrawalInfoRequest.encode(request).finish(); + const promise = this.rpc.request("dydxprotocol.vault.Query", "MegavaultWithdrawalInfo", data); + return promise.then(data => QueryMegavaultWithdrawalInfoResponse.decode(new _m0.Reader(data))); + } + } export const createRpcQueryExtension = (base: QueryClient) => { const rpc = createProtobufRpcClient(base); @@ -103,6 +113,10 @@ export const createRpcQueryExtension = (base: QueryClient) => { vaultParams(request: QueryVaultParamsRequest): Promise { return queryService.vaultParams(request); + }, + + megavaultWithdrawalInfo(request: QueryMegavaultWithdrawalInfoRequest): Promise { + return queryService.megavaultWithdrawalInfo(request); } }; diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts index db52d764dc..2a62eebecc 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts @@ -1,8 +1,8 @@ import { VaultType, VaultTypeSDKType, VaultId, VaultIdSDKType } from "./vault"; import { PageRequest, PageRequestSDKType, PageResponse, PageResponseSDKType } from "../../cosmos/base/query/v1beta1/pagination"; +import { NumShares, NumSharesSDKType, OwnerShare, OwnerShareSDKType } from "./share"; import { Params, ParamsSDKType, QuotingParams, QuotingParamsSDKType, OperatorParams, OperatorParamsSDKType, VaultParams, VaultParamsSDKType } from "./params"; import { SubaccountId, SubaccountIdSDKType } from "../subaccounts/subaccount"; -import { NumShares, NumSharesSDKType, OwnerShare, OwnerShareSDKType } from "./share"; import * as _m0 from "protobufjs/minimal"; import { DeepPartial } from "../../helpers"; /** QueryParamsRequest is a request type for the Params RPC method. */ @@ -177,6 +177,70 @@ export interface QueryVaultParamsResponseSDKType { vault_id?: VaultIdSDKType; vault_params?: VaultParamsSDKType; } +/** + * QueryMegavaultWithdrawalInfoRequest is a request type for the + * MegavaultWithdrawalInfo RPC method. + */ + +export interface QueryMegavaultWithdrawalInfoRequest { + /** Number of shares to withdraw. */ + sharesToWithdraw?: NumShares; +} +/** + * QueryMegavaultWithdrawalInfoRequest is a request type for the + * MegavaultWithdrawalInfo RPC method. + */ + +export interface QueryMegavaultWithdrawalInfoRequestSDKType { + /** Number of shares to withdraw. */ + shares_to_withdraw?: NumSharesSDKType; +} +/** + * QueryMegavaultWithdrawalInfoResponse is a response type for the + * MegavaultWithdrawalInfo RPC method. + */ + +export interface QueryMegavaultWithdrawalInfoResponse { + /** Number of shares to withdraw. */ + sharesToWithdraw?: NumShares; + /** + * Number of quote quantums above `shares` are expected to redeem. + * Withdrawl slippage can be calculated by comparing + * `expected_quote_quantums` with + * `megavault_equity * shares_to_withdraw / total_shares` + */ + + expectedQuoteQuantums: Uint8Array; + /** Equity of megavault (in quote quantums). */ + + megavaultEquity: Uint8Array; + /** Total shares in megavault. */ + + totalShares?: NumShares; +} +/** + * QueryMegavaultWithdrawalInfoResponse is a response type for the + * MegavaultWithdrawalInfo RPC method. + */ + +export interface QueryMegavaultWithdrawalInfoResponseSDKType { + /** Number of shares to withdraw. */ + shares_to_withdraw?: NumSharesSDKType; + /** + * Number of quote quantums above `shares` are expected to redeem. + * Withdrawl slippage can be calculated by comparing + * `expected_quote_quantums` with + * `megavault_equity * shares_to_withdraw / total_shares` + */ + + expected_quote_quantums: Uint8Array; + /** Equity of megavault (in quote quantums). */ + + megavault_equity: Uint8Array; + /** Total shares in megavault. */ + + total_shares?: NumSharesSDKType; +} function createBaseQueryParamsRequest(): QueryParamsRequest { return {}; @@ -804,4 +868,124 @@ export const QueryVaultParamsResponse = { return message; } +}; + +function createBaseQueryMegavaultWithdrawalInfoRequest(): QueryMegavaultWithdrawalInfoRequest { + return { + sharesToWithdraw: undefined + }; +} + +export const QueryMegavaultWithdrawalInfoRequest = { + encode(message: QueryMegavaultWithdrawalInfoRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.sharesToWithdraw !== undefined) { + NumShares.encode(message.sharesToWithdraw, writer.uint32(10).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultWithdrawalInfoRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryMegavaultWithdrawalInfoRequest(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.sharesToWithdraw = NumShares.decode(reader, reader.uint32()); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryMegavaultWithdrawalInfoRequest { + const message = createBaseQueryMegavaultWithdrawalInfoRequest(); + message.sharesToWithdraw = object.sharesToWithdraw !== undefined && object.sharesToWithdraw !== null ? NumShares.fromPartial(object.sharesToWithdraw) : undefined; + return message; + } + +}; + +function createBaseQueryMegavaultWithdrawalInfoResponse(): QueryMegavaultWithdrawalInfoResponse { + return { + sharesToWithdraw: undefined, + expectedQuoteQuantums: new Uint8Array(), + megavaultEquity: new Uint8Array(), + totalShares: undefined + }; +} + +export const QueryMegavaultWithdrawalInfoResponse = { + encode(message: QueryMegavaultWithdrawalInfoResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.sharesToWithdraw !== undefined) { + NumShares.encode(message.sharesToWithdraw, writer.uint32(10).fork()).ldelim(); + } + + if (message.expectedQuoteQuantums.length !== 0) { + writer.uint32(18).bytes(message.expectedQuoteQuantums); + } + + if (message.megavaultEquity.length !== 0) { + writer.uint32(26).bytes(message.megavaultEquity); + } + + if (message.totalShares !== undefined) { + NumShares.encode(message.totalShares, writer.uint32(34).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultWithdrawalInfoResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryMegavaultWithdrawalInfoResponse(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.sharesToWithdraw = NumShares.decode(reader, reader.uint32()); + break; + + case 2: + message.expectedQuoteQuantums = reader.bytes(); + break; + + case 3: + message.megavaultEquity = reader.bytes(); + break; + + case 4: + message.totalShares = NumShares.decode(reader, reader.uint32()); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryMegavaultWithdrawalInfoResponse { + const message = createBaseQueryMegavaultWithdrawalInfoResponse(); + message.sharesToWithdraw = object.sharesToWithdraw !== undefined && object.sharesToWithdraw !== null ? NumShares.fromPartial(object.sharesToWithdraw) : undefined; + message.expectedQuoteQuantums = object.expectedQuoteQuantums ?? new Uint8Array(); + message.megavaultEquity = object.megavaultEquity ?? new Uint8Array(); + message.totalShares = object.totalShares !== undefined && object.totalShares !== null ? NumShares.fromPartial(object.totalShares) : undefined; + return message; + } + }; \ No newline at end of file diff --git a/proto/dydxprotocol/vault/query.proto b/proto/dydxprotocol/vault/query.proto index 57b22b5909..faff37c692 100644 --- a/proto/dydxprotocol/vault/query.proto +++ b/proto/dydxprotocol/vault/query.proto @@ -39,6 +39,13 @@ service Query { rpc VaultParams(QueryVaultParamsRequest) returns (QueryVaultParamsResponse) { option (google.api.http).get = "/dydxprotocol/vault/params/{type}/{number}"; } + + // Queries withdrawal info for megavault. + rpc MegavaultWithdrawalInfo(QueryMegavaultWithdrawalInfoRequest) + returns (QueryMegavaultWithdrawalInfoResponse) { + option (google.api.http).get = + "/dydxprotocol/vault/megavault/withdrawal_info"; + } } // QueryParamsRequest is a request type for the Params RPC method. @@ -119,3 +126,34 @@ message QueryVaultParamsResponse { VaultId vault_id = 1 [ (gogoproto.nullable) = false ]; VaultParams vault_params = 2 [ (gogoproto.nullable) = false ]; } + +// QueryMegavaultWithdrawalInfoRequest is a request type for the +// MegavaultWithdrawalInfo RPC method. +message QueryMegavaultWithdrawalInfoRequest { + // Number of shares to withdraw. + NumShares shares_to_withdraw = 1 [ (gogoproto.nullable) = false ]; +} + +// QueryMegavaultWithdrawalInfoResponse is a response type for the +// MegavaultWithdrawalInfo RPC method. +message QueryMegavaultWithdrawalInfoResponse { + // Number of shares to withdraw. + NumShares shares_to_withdraw = 1 [ (gogoproto.nullable) = false ]; + // Number of quote quantums above `shares` are expected to redeem. + // Withdrawl slippage can be calculated by comparing + // `expected_quote_quantums` with + // `megavault_equity * shares_to_withdraw / total_shares` + bytes expected_quote_quantums = 2 [ + (gogoproto.customtype) = + "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt", + (gogoproto.nullable) = false + ]; + // Equity of megavault (in quote quantums). + bytes megavault_equity = 3 [ + (gogoproto.customtype) = + "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt", + (gogoproto.nullable) = false + ]; + // Total shares in megavault. + NumShares total_shares = 4 [ (gogoproto.nullable) = false ]; +} diff --git a/protocol/x/vault/client/cli/query.go b/protocol/x/vault/client/cli/query.go index 1e72499948..93b2c5a115 100644 --- a/protocol/x/vault/client/cli/query.go +++ b/protocol/x/vault/client/cli/query.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/dydxprotocol/v4-chain/protocol/dtypes" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -28,6 +29,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdQueryListVault()) cmd.AddCommand(CmdQueryTotalShares()) cmd.AddCommand(CmdQueryListOwnerShares()) + cmd.AddCommand(CmdQueryMegavaultWithdrawalInfo()) return cmd } @@ -185,3 +187,37 @@ func CmdQueryListOwnerShares() *cobra.Command { return cmd } + +func CmdQueryMegavaultWithdrawalInfo() *cobra.Command { + cmd := &cobra.Command{ + Use: "megavault-withdrawal-info [shares_to_withdraw]", + Short: "get megavault withdrawal info", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + shares, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + res, err := queryClient.MegavaultWithdrawalInfo( + context.Background(), + &types.QueryMegavaultWithdrawalInfoRequest{ + SharesToWithdraw: types.NumShares{ + NumShares: dtypes.NewIntFromUint64(shares), + }, + }, + ) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/protocol/x/vault/keeper/grpc_query_withdrawal_info.go b/protocol/x/vault/keeper/grpc_query_withdrawal_info.go new file mode 100644 index 0000000000..b29299b25d --- /dev/null +++ b/protocol/x/vault/keeper/grpc_query_withdrawal_info.go @@ -0,0 +1,40 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/dydxprotocol/v4-chain/protocol/dtypes" + "github.com/dydxprotocol/v4-chain/protocol/lib" + "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" +) + +func (k Keeper) MegavaultWithdrawalInfo( + goCtx context.Context, + req *types.QueryMegavaultWithdrawalInfoRequest, +) (*types.QueryMegavaultWithdrawalInfoResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := lib.UnwrapSDKContext(goCtx, types.ModuleName) + + redeemedQuoteQuantums, megavaultEquity, totalShares, err := k.RedeemFromMainAndSubVaults( + ctx, + req.SharesToWithdraw.NumShares.BigInt(), + true, // simulate the redemption (even though queries do execute on branched contexts). + ) + if err != nil { + return nil, err + } + + return &types.QueryMegavaultWithdrawalInfoResponse{ + SharesToWithdraw: req.SharesToWithdraw, + ExpectedQuoteQuantums: dtypes.NewIntFromBigInt(redeemedQuoteQuantums), + MegavaultEquity: dtypes.NewIntFromBigInt(megavaultEquity), + TotalShares: types.NumShares{ + NumShares: dtypes.NewIntFromBigInt(totalShares), + }, + }, nil +} diff --git a/protocol/x/vault/keeper/grpc_query_withdrawal_info_test.go b/protocol/x/vault/keeper/grpc_query_withdrawal_info_test.go new file mode 100644 index 0000000000..507572a9cb --- /dev/null +++ b/protocol/x/vault/keeper/grpc_query_withdrawal_info_test.go @@ -0,0 +1,236 @@ +package keeper_test + +import ( + "math/big" + "testing" + + "github.com/cometbft/cometbft/types" + "github.com/dydxprotocol/v4-chain/protocol/dtypes" + testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" + clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types" + pricestypes "github.com/dydxprotocol/v4-chain/protocol/x/prices/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" + vaulttypes "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" + "github.com/stretchr/testify/require" +) + +func TestQueryMegavaultWithdrawalInfo(t *testing.T) { + tests := map[string]struct { + /* --- Setup --- */ + // Quote quantums that main vault has. + mainVaultBalance *big.Int + // Total shares. + totalShares uint64 + // Vaults. + vaults []VaultSetup + // Query request. + req *vaulttypes.QueryMegavaultWithdrawalInfoRequest + + /* --- Expectations --- */ + res *vaulttypes.QueryMegavaultWithdrawalInfoResponse + expectedErr string + }{ + "Success: Withdraw 10%, 100 quantums in main vault, one sub-vault with 0 leverage and 50 equity": { + mainVaultBalance: big.NewInt(100), + totalShares: 50, + vaults: []VaultSetup{ + { + id: constants.Vault_Clob0, + params: vaulttypes.VaultParams{ + Status: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, + }, + assetQuoteQuantums: big.NewInt(50), + positionBaseQuantums: big.NewInt(0), + clobPair: constants.ClobPair_Btc, + perpetual: constants.BtcUsd_20PercentInitial_10PercentMaintenance, + marketParam: constants.TestMarketParams[0], + marketPrice: constants.TestMarketPrices[0], + }, + }, + req: &vaulttypes.QueryMegavaultWithdrawalInfoRequest{ + SharesToWithdraw: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(5), + }, + }, + res: &vaulttypes.QueryMegavaultWithdrawalInfoResponse{ + SharesToWithdraw: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(5), + }, + ExpectedQuoteQuantums: dtypes.NewInt(15), + MegavaultEquity: dtypes.NewInt(150), + TotalShares: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(50), + }, + }, + }, + "Success: Withdraw ~0.65%, 5_471_283_193_197 quantums in main vault," + + "one sub-vault with 1 leverage and 1_500_000_000 equity": { + mainVaultBalance: big.NewInt(5_471_283_193_197), + totalShares: 128_412_843_128, + vaults: []VaultSetup{ + { + id: constants.Vault_Clob1, + params: vaulttypes.VaultParams{ + Status: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, + }, + // open_notional = 1_000_000_000 * 10^-9 * 3_000 * 10^6 = 3_000_000_000 + // equity = -1_500_000_000 + 3_000_000_000 = 1_500_000_000 + assetQuoteQuantums: big.NewInt(-1_500_000_000), + positionBaseQuantums: big.NewInt(1_000_000_000), + clobPair: constants.ClobPair_Eth, + perpetual: constants.EthUsd_20PercentInitial_10PercentMaintenance, + marketParam: constants.TestMarketParams[1], + marketPrice: constants.TestMarketPrices[1], + }, + }, + req: &vaulttypes.QueryMegavaultWithdrawalInfoRequest{ + SharesToWithdraw: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(831_571_304), + }, + }, + res: &vaulttypes.QueryMegavaultWithdrawalInfoResponse{ + SharesToWithdraw: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(831_571_304), + }, + // expected_quote_quantums + // = shares_to_withdraw / total_shares * main_vault_balance + + // shares_to_withdraw / total_shares * sub_vault_equity * (1 - slippage) + // = 831_571_304 / 128_412_843_128 * 5_471_283_193_197 + + // 831_571_304 / 128_412_843_128 * 1_500_000_000 * (1 - 0.4) + // = 35_430_740_327 + 5_828_187 = 35_436_568_514 + ExpectedQuoteQuantums: dtypes.NewInt(35_436_568_514), + // megavault_equity + // = main_vault_balance + sub_vault_equity + // = 5_471_283_193_197 + 1_500_000_000 + // = 5_472_783_193_197 + MegavaultEquity: dtypes.NewInt(5_472_783_193_197), + TotalShares: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(128_412_843_128), + }, + }, + }, + "Error: Withdraw more than total shares": { + mainVaultBalance: big.NewInt(100), + totalShares: 50, + req: &vaulttypes.QueryMegavaultWithdrawalInfoRequest{ + SharesToWithdraw: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(51), + }, + }, + expectedErr: vaulttypes.ErrInvalidSharesToWithdraw.Error(), + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // Initialize tApp and ctx. + tApp := testapp.NewTestAppBuilder(t).WithGenesisDocFn(func() (genesis types.GenesisDoc) { + genesis = testapp.DefaultGenesis() + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *satypes.GenesisState) { + subaccounts := []satypes.Subaccount{ + { + Id: &vaulttypes.MegavaultMainSubaccount, + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: assetstypes.AssetUsdc.Id, + Quantums: dtypes.NewIntFromBigInt(tc.mainVaultBalance), + }, + }, + }, + } + for _, vault := range tc.vaults { + subaccounts = append(subaccounts, satypes.Subaccount{ + Id: vault.id.ToSubaccountId(), + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: assetstypes.AssetUsdc.Id, + Quantums: dtypes.NewIntFromBigInt(vault.assetQuoteQuantums), + }, + }, + PerpetualPositions: []*satypes.PerpetualPosition{ + { + PerpetualId: vault.perpetual.Params.Id, + Quantums: dtypes.NewIntFromBigInt(vault.positionBaseQuantums), + }, + }, + }) + } + genesisState.Subaccounts = subaccounts + }, + ) + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *vaulttypes.GenesisState) { + genesisState.TotalShares = vaulttypes.NumShares{ + NumShares: dtypes.NewIntFromUint64(tc.totalShares), + } + vaults := make([]vaulttypes.Vault, len(tc.vaults)) + for i, vault := range tc.vaults { + vaults[i] = vaulttypes.Vault{ + VaultId: vault.id, + VaultParams: vault.params, + } + } + genesisState.Vaults = vaults + }, + ) + // Initialize prices. + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *pricestypes.GenesisState) { + marketParams := make([]pricestypes.MarketParam, len(tc.vaults)) + marketPrices := make([]pricestypes.MarketPrice, len(tc.vaults)) + for i, vault := range tc.vaults { + vault.marketParam.Id = vault.id.Number + marketParams[i] = vault.marketParam + vault.marketPrice.Id = vault.id.Number + marketPrices[i] = vault.marketPrice + } + genesisState.MarketParams = marketParams + genesisState.MarketPrices = marketPrices + }, + ) + // Initialize perpetuals. + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *perptypes.GenesisState) { + genesisState.LiquidityTiers = constants.LiquidityTiers + perpetuals := make([]perptypes.Perpetual, len(tc.vaults)) + for i, vault := range tc.vaults { + vault.perpetual.Params.Id = vault.id.Number + perpetuals[i] = vault.perpetual + } + genesisState.Perpetuals = perpetuals + }, + ) + // Initialize clob pairs. + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *clobtypes.GenesisState) { + clobPairs := make([]clobtypes.ClobPair, len(tc.vaults)) + for i, vault := range tc.vaults { + vault.clobPair.Id = vault.id.Number + clobPairs[i] = vault.clobPair + } + genesisState.ClobPairs = clobPairs + }, + ) + return genesis + }).Build() + ctx := tApp.InitChain() + + response, err := tApp.App.VaultKeeper.MegavaultWithdrawalInfo(ctx, tc.req) + if tc.expectedErr != "" { + require.ErrorContains(t, err, tc.expectedErr) + } else { + require.NoError(t, err) + require.Equal(t, tc.res, response) + } + }) + } +} diff --git a/protocol/x/vault/keeper/withdraw.go b/protocol/x/vault/keeper/withdraw.go index 957518e7c5..436effd9d6 100644 --- a/protocol/x/vault/keeper/withdraw.go +++ b/protocol/x/vault/keeper/withdraw.go @@ -150,126 +150,15 @@ func (k Keeper) WithdrawFromMegavault( ) } - // 2. Redeem from main vault. - totalShares := k.GetTotalShares(ctx).NumShares.BigInt() - megavaultEquity, err := k.GetSubaccountEquity(ctx, types.MegavaultMainSubaccount) - redeemedQuoteQuantums = new(big.Int).Set(megavaultEquity) + // 2. Redeem from main and sub vaults. + // Note that in below function, quote quantums redeemed from each sub vault are transferred to the main vault. + redeemedQuoteQuantums, megavaultEquity, totalShares, err := + k.RedeemFromMainAndSubVaults(ctx, sharesToWithdraw, false) // set `simulate` to false. if err != nil { - log.ErrorLogWithError(ctx, "Megavault withdrawal: failed to get megavault main vault equity", err) return nil, err } - redeemedQuoteQuantums.Mul(redeemedQuoteQuantums, sharesToWithdraw) - redeemedQuoteQuantums.Quo(redeemedQuoteQuantums, totalShares) - - // 3. Redeem from each sub vault. - vaultParamsIterator := k.getVaultParamsIterator(ctx) - defer vaultParamsIterator.Close() - for ; vaultParamsIterator.Valid(); vaultParamsIterator.Next() { - var vaultParams types.VaultParams - k.cdc.MustUnmarshal(vaultParamsIterator.Value(), &vaultParams) - // Skip deactivated vaults. - if vaultParams.Status == types.VaultStatus_VAULT_STATUS_DEACTIVATED { - continue - } - - vaultId, err := types.GetVaultIdFromStateKey(vaultParamsIterator.Key()) - if err != nil { - log.ErrorLogWithError( - ctx, - "Megavault withdrawal: error when getting vault ID from state key. Skipping this vault", - err, - ) - continue - } - - _, perpetual, marketParam, marketPrice, err := k.GetVaultClobPerpAndMarket(ctx, *vaultId) - if err != nil { - log.ErrorLogWithError( - ctx, - "Megavault withdrawal: error when getting perpetual and market. Skipping this vault", - err, - "Vault ID", - vaultId, - ) - continue - } - leverage, equity, err := k.GetVaultLeverageAndEquity(ctx, *vaultId, &perpetual, &marketPrice) - if err != nil { - log.ErrorLogWithError( - ctx, - "Megavault withdrawal: error when getting vault leverage and equity. Skipping this vault", - err, - "Vault ID", - vaultId, - ) - continue - } - - slippage, err := k.GetVaultWithdrawalSlippage( - ctx, - *vaultId, - sharesToWithdraw, - totalShares, - leverage, - &perpetual, - &marketParam, - ) - if err != nil { - log.ErrorLogWithError( - ctx, - "Megavault withdrawal: error when getting vault withdrawal slippage. Skipping this vault", - err, - "Vault ID", - vaultId, - ) - continue - } - - // Transfer `equity * shares / totalShares * (1 - slippage)` from sub vault to main vault. - redeemedFromSubVault := new(big.Rat).SetFrac(equity, big.NewInt(1)) - redeemedFromSubVault.Mul(redeemedFromSubVault, new(big.Rat).SetFrac(sharesToWithdraw, totalShares)) - redeemedFromSubVault.Mul(redeemedFromSubVault, new(big.Rat).Sub(lib.BigRat1(), slippage)) - quantumsToTransfer := new(big.Int).Quo(redeemedFromSubVault.Num(), redeemedFromSubVault.Denom()) - if quantumsToTransfer.Sign() <= 0 || !quantumsToTransfer.IsUint64() { - log.InfoLog( - ctx, - "Megavault withdrawal: quantums to transfer is invalid. Skipping this vault", - "Vault ID", - vaultId, - "Quantums", - quantumsToTransfer, - ) - continue - } - err = k.sendingKeeper.ProcessTransfer( - ctx, - &sendingtypes.Transfer{ - Sender: *vaultId.ToSubaccountId(), - Recipient: types.MegavaultMainSubaccount, - AssetId: assetstypes.AssetUsdc.Id, - Amount: quantumsToTransfer.Uint64(), // validated above. - }, - ) - if err != nil { - log.ErrorLogWithError( - ctx, - "Megavault withdrawal: error when transferring from sub vault to main vault. Skipping this vault", - err, - "Vault ID", - vaultId, - "Quantums", - quantumsToTransfer, - ) - continue - } - - // Increment total redeemed quote quantums and record this vault's equity as part of megavault equity. - redeemedQuoteQuantums.Add(redeemedQuoteQuantums, quantumsToTransfer) - megavaultEquity.Add(megavaultEquity, equity) - } - - // 4. Return error if redeemed quantums is invalid. + // 3. Return error if redeemed quantums is invalid. if redeemedQuoteQuantums.Sign() <= 0 || !redeemedQuoteQuantums.IsUint64() || redeemedQuoteQuantums.Cmp(minQuoteQuantums) < 0 { return nil, errorsmod.Wrapf( @@ -280,7 +169,7 @@ func (k Keeper) WithdrawFromMegavault( ) } - // 5. Transfer from main vault to destination subaccount. + // 4. Transfer from main vault to destination subaccount. err = k.sendingKeeper.ProcessTransfer( ctx, &sendingtypes.Transfer{ @@ -303,7 +192,7 @@ func (k Keeper) WithdrawFromMegavault( return nil, err } - // 6. Decrement total and owner shares. + // 5. Decrement total and owner shares. if err = k.SetTotalShares( ctx, types.BigIntToNumShares(new(big.Int).Sub(totalShares, sharesToWithdraw)), @@ -332,3 +221,206 @@ func (k Keeper) WithdrawFromMegavault( return redeemedQuoteQuantums, nil } + +// RedeemFromMainAndSubVaults redeems `shares` number of shares from main and sub vaults. +// If and only if `simulate` is false, logs are enabled and quote quantums redeemed from each +// sub vault are transferred to the main vault. +func (k Keeper) RedeemFromMainAndSubVaults( + ctx sdk.Context, + shares *big.Int, + simulate bool, +) ( + redeemedQuoteQuantums *big.Int, + megavaultEquity *big.Int, + totalShares *big.Int, + err error, +) { + // Redeem from main vault. + totalShares = k.GetTotalShares(ctx).NumShares.BigInt() + if shares.Cmp(totalShares) > 0 { + return nil, nil, totalShares, errorsmod.Wrapf( + types.ErrInvalidSharesToWithdraw, + "shares to withdraw %s exceeds total shares %s", + shares, + totalShares, + ) + } + megavaultEquity, err = k.GetSubaccountEquity(ctx, types.MegavaultMainSubaccount) + if err != nil { + if simulate { + log.DebugLog(ctx, "Megavault withdrawal: failed to get megavault main vault equity", "error", err) + } else { + log.ErrorLogWithError(ctx, "Megavault withdrawal: failed to get megavault main vault equity", err) + } + return nil, nil, totalShares, err + } + redeemedQuoteQuantums = new(big.Int).Set(megavaultEquity) + redeemedQuoteQuantums.Mul(redeemedQuoteQuantums, shares) + redeemedQuoteQuantums.Quo(redeemedQuoteQuantums, totalShares) + + // Redeem from each sub vault. + vaultParamsIterator := k.getVaultParamsIterator(ctx) + defer vaultParamsIterator.Close() + for ; vaultParamsIterator.Valid(); vaultParamsIterator.Next() { + var vaultParams types.VaultParams + k.cdc.MustUnmarshal(vaultParamsIterator.Value(), &vaultParams) + // Skip deactivated vaults. + if vaultParams.Status == types.VaultStatus_VAULT_STATUS_DEACTIVATED { + continue + } + + vaultId, err := types.GetVaultIdFromStateKey(vaultParamsIterator.Key()) + if err != nil { + if simulate { + log.DebugLog( + ctx, + "Megavault withdrawal: failed to get vault ID from state key. Skipping this vault", + "error", + err, + ) + } else { + log.ErrorLogWithError( + ctx, + "Megavault withdrawal: error when getting vault ID from state key. Skipping this vault", + err, + ) + } + continue + } + + _, perpetual, marketParam, marketPrice, err := k.GetVaultClobPerpAndMarket(ctx, *vaultId) + if err != nil { + if simulate { + log.DebugLog( + ctx, + "Megavault withdrawal: failed to get perpetual and market. Skipping this vault", + "Vault ID", + vaultId, + "Error", + err, + ) + } else { + log.ErrorLogWithError( + ctx, + "Megavault withdrawal: error when getting perpetual and market. Skipping this vault", + err, + "Vault ID", + vaultId, + ) + } + continue + } + leverage, equity, err := k.GetVaultLeverageAndEquity(ctx, *vaultId, &perpetual, &marketPrice) + if err != nil { + if simulate { + log.DebugLog( + ctx, + "Megavault withdrawal: failed to get vault leverage and equity. Skipping this vault", + "Vault ID", + vaultId, + "Error", + err, + ) + } else { + log.ErrorLogWithError( + ctx, + "Megavault withdrawal: error when getting vault leverage and equity. Skipping this vault", + err, + "Vault ID", + vaultId, + ) + } + continue + } + + slippage, err := k.GetVaultWithdrawalSlippage( + ctx, + *vaultId, + shares, + totalShares, + leverage, + &perpetual, + &marketParam, + ) + if err != nil { + if simulate { + log.DebugLog( + ctx, + "Megavault withdrawal: failed to get vault withdrawal slippage. Skipping this vault", + "Vault ID", + vaultId, + "Error", + err, + ) + } else { + log.ErrorLogWithError( + ctx, + "Megavault withdrawal: error when getting vault withdrawal slippage. Skipping this vault", + err, + "Vault ID", + vaultId, + ) + } + continue + } + + // Amount redeemed from this sub-vault is `equity * shares / totalShares * (1 - slippage)`. + redeemedFromSubVault := new(big.Rat).SetFrac(equity, big.NewInt(1)) + redeemedFromSubVault.Mul(redeemedFromSubVault, new(big.Rat).SetFrac(shares, totalShares)) + redeemedFromSubVault.Mul(redeemedFromSubVault, new(big.Rat).Sub(lib.BigRat1(), slippage)) + quantumsToTransfer := new(big.Int).Quo(redeemedFromSubVault.Num(), redeemedFromSubVault.Denom()) + + if quantumsToTransfer.Sign() <= 0 || !quantumsToTransfer.IsUint64() { + if simulate { + log.DebugLog( + ctx, + "Megavault withdrawal: quantums to transfer is invalid. Skipping this vault", + "Vault ID", + vaultId, + "Quantums", + quantumsToTransfer, + ) + } else { + log.ErrorLog( + ctx, + "Megavault withdrawal: quantums to transfer is invalid. Skipping this vault", + "Vault ID", + vaultId, + "Quantums", + quantumsToTransfer, + ) + } + continue + } + if !simulate { + // Transfer from sub vault to main vault. + err = k.sendingKeeper.ProcessTransfer( + ctx, + &sendingtypes.Transfer{ + Sender: *vaultId.ToSubaccountId(), + Recipient: types.MegavaultMainSubaccount, + AssetId: assetstypes.AssetUsdc.Id, + Amount: quantumsToTransfer.Uint64(), // validated above. + }, + ) + if err != nil { + log.ErrorLogWithError( + ctx, + "Megavault withdrawal: error when transferring from sub vault to main vault. Skipping this vault", + err, + "Vault ID", + vaultId, + "Quantums", + quantumsToTransfer, + ) + continue + } + } + + // Increment total redeemed quote quantums and record this vault's equity as part of megavault equity. + redeemedQuoteQuantums.Add(redeemedQuoteQuantums, quantumsToTransfer) + megavaultEquity.Add(megavaultEquity, equity) + } + + return redeemedQuoteQuantums, megavaultEquity, totalShares, nil +} diff --git a/protocol/x/vault/types/query.pb.go b/protocol/x/vault/types/query.pb.go index 4eeaa864f5..3a20349960 100644 --- a/protocol/x/vault/types/query.pb.go +++ b/protocol/x/vault/types/query.pb.go @@ -636,6 +636,116 @@ func (m *QueryVaultParamsResponse) GetVaultParams() VaultParams { return VaultParams{} } +// QueryMegavaultWithdrawalInfoRequest is a request type for the +// MegavaultWithdrawalInfo RPC method. +type QueryMegavaultWithdrawalInfoRequest struct { + // Number of shares to withdraw. + SharesToWithdraw NumShares `protobuf:"bytes,1,opt,name=shares_to_withdraw,json=sharesToWithdraw,proto3" json:"shares_to_withdraw"` +} + +func (m *QueryMegavaultWithdrawalInfoRequest) Reset() { *m = QueryMegavaultWithdrawalInfoRequest{} } +func (m *QueryMegavaultWithdrawalInfoRequest) String() string { return proto.CompactTextString(m) } +func (*QueryMegavaultWithdrawalInfoRequest) ProtoMessage() {} +func (*QueryMegavaultWithdrawalInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_478fb8dc0ff21ea6, []int{12} +} +func (m *QueryMegavaultWithdrawalInfoRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMegavaultWithdrawalInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMegavaultWithdrawalInfoRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMegavaultWithdrawalInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMegavaultWithdrawalInfoRequest.Merge(m, src) +} +func (m *QueryMegavaultWithdrawalInfoRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryMegavaultWithdrawalInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMegavaultWithdrawalInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMegavaultWithdrawalInfoRequest proto.InternalMessageInfo + +func (m *QueryMegavaultWithdrawalInfoRequest) GetSharesToWithdraw() NumShares { + if m != nil { + return m.SharesToWithdraw + } + return NumShares{} +} + +// QueryMegavaultWithdrawalInfoResponse is a response type for the +// MegavaultWithdrawalInfo RPC method. +type QueryMegavaultWithdrawalInfoResponse struct { + // Number of shares to withdraw. + SharesToWithdraw NumShares `protobuf:"bytes,1,opt,name=shares_to_withdraw,json=sharesToWithdraw,proto3" json:"shares_to_withdraw"` + // Number of quote quantums above `shares` are expected to redeem. + // Withdrawl slippage can be calculated by comparing + // `expected_quote_quantums` with + // `megavault_equity * shares_to_withdraw / total_shares` + ExpectedQuoteQuantums github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,2,opt,name=expected_quote_quantums,json=expectedQuoteQuantums,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"expected_quote_quantums"` + // Equity of megavault (in quote quantums). + MegavaultEquity github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,3,opt,name=megavault_equity,json=megavaultEquity,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"megavault_equity"` + // Total shares in megavault. + TotalShares NumShares `protobuf:"bytes,4,opt,name=total_shares,json=totalShares,proto3" json:"total_shares"` +} + +func (m *QueryMegavaultWithdrawalInfoResponse) Reset() { *m = QueryMegavaultWithdrawalInfoResponse{} } +func (m *QueryMegavaultWithdrawalInfoResponse) String() string { return proto.CompactTextString(m) } +func (*QueryMegavaultWithdrawalInfoResponse) ProtoMessage() {} +func (*QueryMegavaultWithdrawalInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_478fb8dc0ff21ea6, []int{13} +} +func (m *QueryMegavaultWithdrawalInfoResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMegavaultWithdrawalInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMegavaultWithdrawalInfoResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMegavaultWithdrawalInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMegavaultWithdrawalInfoResponse.Merge(m, src) +} +func (m *QueryMegavaultWithdrawalInfoResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryMegavaultWithdrawalInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMegavaultWithdrawalInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMegavaultWithdrawalInfoResponse proto.InternalMessageInfo + +func (m *QueryMegavaultWithdrawalInfoResponse) GetSharesToWithdraw() NumShares { + if m != nil { + return m.SharesToWithdraw + } + return NumShares{} +} + +func (m *QueryMegavaultWithdrawalInfoResponse) GetTotalShares() NumShares { + if m != nil { + return m.TotalShares + } + return NumShares{} +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "dydxprotocol.vault.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "dydxprotocol.vault.QueryParamsResponse") @@ -649,71 +759,83 @@ func init() { proto.RegisterType((*QueryMegavaultOwnerSharesResponse)(nil), "dydxprotocol.vault.QueryMegavaultOwnerSharesResponse") proto.RegisterType((*QueryVaultParamsRequest)(nil), "dydxprotocol.vault.QueryVaultParamsRequest") proto.RegisterType((*QueryVaultParamsResponse)(nil), "dydxprotocol.vault.QueryVaultParamsResponse") + proto.RegisterType((*QueryMegavaultWithdrawalInfoRequest)(nil), "dydxprotocol.vault.QueryMegavaultWithdrawalInfoRequest") + proto.RegisterType((*QueryMegavaultWithdrawalInfoResponse)(nil), "dydxprotocol.vault.QueryMegavaultWithdrawalInfoResponse") } func init() { proto.RegisterFile("dydxprotocol/vault/query.proto", fileDescriptor_478fb8dc0ff21ea6) } var fileDescriptor_478fb8dc0ff21ea6 = []byte{ - // 939 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6f, 0xe3, 0x44, - 0x14, 0x8e, 0x93, 0x36, 0xcb, 0x4e, 0xb2, 0x8b, 0x18, 0x42, 0x09, 0xd9, 0xc5, 0xd9, 0x5a, 0x62, - 0x97, 0x76, 0x17, 0x5b, 0x09, 0x8b, 0x90, 0x10, 0x42, 0xbb, 0x3d, 0xc0, 0xf6, 0x00, 0x6d, 0xdc, - 0x8a, 0x03, 0x12, 0x84, 0x49, 0x32, 0x75, 0x8d, 0x1c, 0x8f, 0x63, 0x8f, 0x43, 0x43, 0xd5, 0x0b, - 0x88, 0x03, 0x37, 0x24, 0xae, 0x5c, 0xe0, 0x8e, 0x38, 0x22, 0xfe, 0x83, 0x1e, 0x2b, 0x71, 0x41, - 0x1c, 0x2a, 0xd4, 0xf2, 0x87, 0x20, 0xcf, 0x4c, 0xe2, 0x1f, 0xb1, 0x53, 0x6f, 0x95, 0x4b, 0xe4, - 0xbc, 0x79, 0xef, 0x7b, 0xdf, 0xbc, 0x1f, 0x9f, 0x0d, 0xe4, 0xc1, 0x64, 0x70, 0xe4, 0xb8, 0x84, - 0x92, 0x3e, 0xb1, 0xb4, 0x31, 0xf2, 0x2d, 0xaa, 0x8d, 0x7c, 0xec, 0x4e, 0x54, 0x66, 0x84, 0x30, - 0x7a, 0xae, 0xb2, 0xf3, 0x46, 0xcd, 0x20, 0x06, 0x61, 0x36, 0x2d, 0x78, 0xe2, 0x9e, 0x8d, 0xbb, - 0x06, 0x21, 0x86, 0x85, 0x35, 0xe4, 0x98, 0x1a, 0xb2, 0x6d, 0x42, 0x11, 0x35, 0x89, 0xed, 0x89, - 0xd3, 0xcd, 0x3e, 0xf1, 0x86, 0xc4, 0xd3, 0x7a, 0xc8, 0xc3, 0x3c, 0x81, 0x36, 0x6e, 0xf5, 0x30, - 0x45, 0x2d, 0xcd, 0x41, 0x86, 0x69, 0x33, 0x67, 0xe1, 0xbb, 0x11, 0xe3, 0xe4, 0xf9, 0x3d, 0xd4, - 0xef, 0x13, 0xdf, 0xa6, 0x5e, 0xe4, 0x59, 0xb8, 0x36, 0x53, 0xe8, 0x3b, 0xc8, 0x45, 0xc3, 0x69, - 0xde, 0xb4, 0xfb, 0x79, 0x87, 0xc8, 0xc5, 0x0b, 0xce, 0xd9, 0x2f, 0x3f, 0x57, 0x6a, 0x00, 0x76, - 0x02, 0xb6, 0xbb, 0x0c, 0x54, 0xc7, 0x23, 0x1f, 0x7b, 0x54, 0xf9, 0xae, 0x08, 0x5e, 0x8e, 0x99, - 0x3d, 0x87, 0xd8, 0x1e, 0x86, 0xef, 0x81, 0x32, 0xcf, 0x5e, 0x97, 0xee, 0x49, 0x6f, 0x56, 0xda, - 0x0d, 0x75, 0xbe, 0x7c, 0x2a, 0x8f, 0xd9, 0x2a, 0x9f, 0x9e, 0x37, 0x0b, 0x75, 0x49, 0x17, 0x11, - 0xf0, 0x73, 0xb0, 0x36, 0xc0, 0x07, 0x81, 0x47, 0x77, 0xe4, 0x13, 0x6a, 0xda, 0x46, 0x57, 0x60, - 0x15, 0x19, 0xd6, 0x7a, 0x1a, 0x56, 0x87, 0x7b, 0x0a, 0xc8, 0x95, 0x00, 0x52, 0xaf, 0x09, 0x98, - 0xd8, 0x19, 0xec, 0x80, 0x17, 0x89, 0x83, 0x5d, 0x44, 0x89, 0x3b, 0xc5, 0x2d, 0x31, 0x5c, 0x25, - 0x0d, 0x77, 0x47, 0xb8, 0xc6, 0x80, 0x6f, 0x93, 0x98, 0x55, 0xf9, 0x02, 0xbc, 0xc4, 0x8a, 0xf0, - 0x69, 0x10, 0x22, 0x4a, 0x03, 0x5b, 0x60, 0x85, 0x4e, 0x1c, 0xcc, 0x0a, 0x70, 0xbb, 0xfd, 0x7a, - 0x1a, 0x38, 0xf3, 0xdf, 0x9f, 0x38, 0x58, 0x67, 0xae, 0x70, 0x0d, 0x94, 0x6d, 0x7f, 0xd8, 0xc3, - 0x2e, 0xbb, 0xe9, 0x2d, 0x5d, 0xfc, 0x53, 0xfe, 0x2c, 0x89, 0xe2, 0x8b, 0x04, 0xa2, 0xc8, 0xef, - 0x83, 0x17, 0x18, 0x4e, 0xd7, 0x1c, 0x88, 0x32, 0xdf, 0xc9, 0xcc, 0xb2, 0x3d, 0x10, 0xdc, 0x6f, - 0x8c, 0xf9, 0x5f, 0xd8, 0x01, 0xb7, 0xc2, 0x29, 0x0a, 0x20, 0x78, 0x75, 0xef, 0xc7, 0x21, 0x22, - 0x43, 0xa7, 0xee, 0xcd, 0x9e, 0x67, 0x68, 0x55, 0x2f, 0x62, 0x83, 0x5f, 0x82, 0x32, 0x1e, 0xf9, - 0x26, 0x9d, 0xb0, 0x8a, 0x56, 0xb7, 0x9e, 0x05, 0x3e, 0xff, 0x9c, 0x37, 0x9f, 0x18, 0x26, 0x3d, - 0xf4, 0x7b, 0x6a, 0x9f, 0x0c, 0xb5, 0xf8, 0x98, 0x3d, 0x7e, 0xab, 0x7f, 0x88, 0x4c, 0x5b, 0x9b, - 0x59, 0x06, 0x41, 0x21, 0x3c, 0x75, 0x0f, 0xbb, 0x26, 0xb2, 0xcc, 0x6f, 0x50, 0xcf, 0xc2, 0xdb, - 0x36, 0xd5, 0x05, 0x2e, 0x3c, 0x00, 0x37, 0x4d, 0x7b, 0x8c, 0x6d, 0x4a, 0xdc, 0x49, 0x7d, 0x65, - 0xc9, 0x49, 0x42, 0x68, 0xf8, 0x0c, 0x54, 0x79, 0x69, 0xc5, 0x84, 0xac, 0xb2, 0xda, 0x34, 0x33, - 0xcb, 0x1b, 0x1b, 0x8f, 0xca, 0x38, 0x34, 0x29, 0x5d, 0xf0, 0x0a, 0x6b, 0xdd, 0x53, 0xcb, 0x62, - 0x9e, 0xd3, 0xd5, 0x81, 0x1f, 0x02, 0x10, 0x2e, 0xbc, 0xe8, 0xdf, 0x7d, 0x95, 0xab, 0x83, 0x1a, - 0xa8, 0x83, 0xca, 0xe5, 0x47, 0xa8, 0x83, 0xba, 0x8b, 0x0c, 0x2c, 0x62, 0xf5, 0x48, 0xa4, 0xf2, - 0x8b, 0x04, 0xd6, 0x92, 0x19, 0xc4, 0x80, 0x7c, 0x00, 0xca, 0x8c, 0x4a, 0xb0, 0x85, 0xa5, 0xf9, - 0xde, 0x4e, 0x37, 0x27, 0x39, 0x58, 0xba, 0x88, 0x82, 0x1f, 0xc5, 0x28, 0xf2, 0xf9, 0x78, 0x70, - 0x25, 0x45, 0x01, 0x12, 0xe5, 0xa8, 0x80, 0x7b, 0x2c, 0xcd, 0xc7, 0xd8, 0x40, 0x0c, 0x7b, 0x9f, - 0x50, 0x64, 0xed, 0x05, 0xf2, 0x33, 0x93, 0x12, 0x0c, 0xd6, 0x17, 0xf8, 0x88, 0x1b, 0x3d, 0x01, - 0x55, 0x1a, 0x98, 0xbb, 0x4c, 0xba, 0xa6, 0xea, 0x92, 0xba, 0x5c, 0x9f, 0xf8, 0x43, 0x11, 0x5c, - 0xa1, 0x21, 0x92, 0xf2, 0x55, 0x92, 0xca, 0xce, 0xd7, 0x36, 0x76, 0x63, 0x54, 0x12, 0xad, 0x29, - 0x5d, 0xbb, 0x35, 0xbf, 0x4b, 0xc9, 0x3b, 0xc5, 0x92, 0x89, 0x3b, 0x3d, 0x05, 0x55, 0x12, 0x98, - 0xc3, 0x3b, 0x05, 0xbd, 0x92, 0x53, 0xd5, 0x68, 0x16, 0xae, 0x57, 0x48, 0x08, 0xb5, 0xbc, 0x46, - 0x0d, 0xc0, 0xab, 0xe1, 0x3c, 0xc4, 0xa4, 0x7e, 0x99, 0x7a, 0xf6, 0xab, 0x04, 0xea, 0xf3, 0x69, - 0x96, 0xa2, 0x6a, 0xc9, 0xc5, 0x2d, 0x5e, 0x77, 0x71, 0xdb, 0xbf, 0xdd, 0x00, 0xab, 0x8c, 0x24, - 0x3c, 0x01, 0x65, 0xf1, 0xee, 0xc8, 0x5e, 0xa0, 0x58, 0xad, 0x1a, 0x0f, 0xae, 0xf4, 0xe3, 0x97, - 0x55, 0x94, 0x6f, 0xff, 0xfa, 0xef, 0xa7, 0xe2, 0x5d, 0xd8, 0xd0, 0x32, 0xdf, 0xdf, 0xf0, 0x07, - 0x09, 0xac, 0x32, 0xae, 0xf0, 0x8d, 0xab, 0xf6, 0x97, 0x67, 0xcf, 0xb9, 0xe6, 0x4a, 0x8b, 0x25, - 0x7f, 0x08, 0x37, 0xb4, 0xac, 0x77, 0xbf, 0x76, 0x1c, 0xf4, 0xf1, 0x44, 0x3b, 0xe6, 0x8d, 0x3b, - 0x81, 0xdf, 0x4b, 0xe0, 0xe6, 0x4c, 0x67, 0xe0, 0x46, 0x66, 0xa2, 0xa4, 0xda, 0x35, 0x36, 0xf3, - 0xb8, 0x0a, 0x5e, 0xeb, 0x8c, 0xd7, 0x1d, 0xf8, 0x5a, 0x26, 0x2f, 0xf8, 0x87, 0x04, 0x6a, 0x69, - 0x42, 0x01, 0x1f, 0x67, 0xe6, 0x59, 0xa0, 0x3d, 0x8d, 0x77, 0x9e, 0x33, 0x4a, 0x10, 0x6d, 0x33, - 0xa2, 0x8f, 0xe0, 0x66, 0x1a, 0xd1, 0xe1, 0x34, 0x52, 0x8b, 0x2a, 0x56, 0x9c, 0x79, 0x44, 0x0e, - 0xf2, 0x30, 0x9f, 0x97, 0xaa, 0x3c, 0xcc, 0x53, 0x34, 0x27, 0x2f, 0xf3, 0xa8, 0x2e, 0xc1, 0x9f, - 0x25, 0x50, 0x89, 0xec, 0x0c, 0x7c, 0xb8, 0x78, 0xcc, 0xe2, 0x1b, 0xf1, 0x28, 0x9f, 0x73, 0x1e, - 0x7a, 0x7c, 0x2d, 0x92, 0xa3, 0xb9, 0xd5, 0x39, 0xbd, 0x90, 0xa5, 0xb3, 0x0b, 0x59, 0xfa, 0xf7, - 0x42, 0x96, 0x7e, 0xbc, 0x94, 0x0b, 0x67, 0x97, 0x72, 0xe1, 0xef, 0x4b, 0xb9, 0xf0, 0xd9, 0xbb, - 0xf9, 0xbf, 0x0c, 0x8e, 0x44, 0x0e, 0xf6, 0x81, 0xd0, 0x2b, 0x33, 0xfb, 0xdb, 0xff, 0x07, 0x00, - 0x00, 0xff, 0xff, 0x07, 0x2f, 0xa4, 0x54, 0x1c, 0x0c, 0x00, 0x00, + // 1090 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xe6, 0x8f, 0x69, 0x9f, 0xdd, 0x3f, 0x0c, 0x69, 0x12, 0xdc, 0xe2, 0x34, 0x0b, 0xb4, + 0x24, 0x6d, 0x77, 0x95, 0xd0, 0xaa, 0x08, 0x21, 0xd4, 0x46, 0xa2, 0x34, 0x07, 0x68, 0xed, 0x44, + 0x20, 0x21, 0xc1, 0x32, 0xb6, 0x27, 0xce, 0x22, 0x7b, 0xc7, 0xde, 0x9d, 0x75, 0x62, 0xaa, 0x48, + 0x08, 0xc4, 0x81, 0x1b, 0x12, 0x57, 0x2e, 0xf0, 0x05, 0x38, 0x22, 0xce, 0x5c, 0x7a, 0xac, 0xc4, + 0x05, 0x71, 0xa8, 0x50, 0xc2, 0x37, 0xe0, 0x0b, 0xa0, 0x9d, 0x79, 0x5e, 0xef, 0xda, 0xbb, 0xce, + 0xb6, 0x32, 0x97, 0xc8, 0x99, 0x79, 0xef, 0xf7, 0x7e, 0xf3, 0xfe, 0xfc, 0xde, 0x42, 0xa9, 0xde, + 0xab, 0x1f, 0xb4, 0x5d, 0x2e, 0x78, 0x8d, 0x37, 0xcd, 0x2e, 0xf5, 0x9b, 0xc2, 0xec, 0xf8, 0xcc, + 0xed, 0x19, 0xf2, 0x90, 0x90, 0xe8, 0xbd, 0x21, 0xef, 0x8b, 0xf3, 0x0d, 0xde, 0xe0, 0xf2, 0xcc, + 0x0c, 0x7e, 0x29, 0xcb, 0xe2, 0xa5, 0x06, 0xe7, 0x8d, 0x26, 0x33, 0x69, 0xdb, 0x36, 0xa9, 0xe3, + 0x70, 0x41, 0x85, 0xcd, 0x1d, 0x0f, 0x6f, 0xd7, 0x6a, 0xdc, 0x6b, 0x71, 0xcf, 0xac, 0x52, 0x8f, + 0xa9, 0x00, 0x66, 0x77, 0xbd, 0xca, 0x04, 0x5d, 0x37, 0xdb, 0xb4, 0x61, 0x3b, 0xd2, 0x18, 0x6d, + 0x57, 0x63, 0x9c, 0x3c, 0xbf, 0x4a, 0x6b, 0x35, 0xee, 0x3b, 0xc2, 0x8b, 0xfc, 0x46, 0xd3, 0xe5, + 0x04, 0xfa, 0x6d, 0xea, 0xd2, 0x56, 0x3f, 0x6e, 0xd2, 0xfb, 0xbc, 0x3d, 0xea, 0xb2, 0x31, 0xf7, + 0xf2, 0xaf, 0xba, 0xd7, 0xe7, 0x81, 0x94, 0x03, 0xb6, 0x0f, 0x25, 0x68, 0x85, 0x75, 0x7c, 0xe6, + 0x09, 0xfd, 0x9b, 0x69, 0x78, 0x29, 0x76, 0xec, 0xb5, 0xb9, 0xe3, 0x31, 0xf2, 0x36, 0xe4, 0x54, + 0xf4, 0x25, 0xed, 0xb2, 0xf6, 0x46, 0x7e, 0xa3, 0x68, 0x8c, 0xa6, 0xcf, 0x50, 0x3e, 0x9b, 0xb9, + 0xc7, 0x4f, 0x97, 0xa7, 0x96, 0xb4, 0x0a, 0x7a, 0x90, 0x4f, 0x61, 0xa1, 0xce, 0x76, 0x03, 0x0b, + 0xab, 0xe3, 0x73, 0x61, 0x3b, 0x0d, 0x0b, 0xb1, 0xa6, 0x25, 0xd6, 0x4a, 0x12, 0x56, 0x59, 0x59, + 0x22, 0xe4, 0x6c, 0x00, 0x59, 0x99, 0x47, 0x98, 0xd8, 0x1d, 0x29, 0xc3, 0x39, 0xde, 0x66, 0x2e, + 0x15, 0xdc, 0xed, 0xe3, 0xce, 0x48, 0x5c, 0x3d, 0x09, 0xf7, 0x01, 0x9a, 0xc6, 0x80, 0xcf, 0xf2, + 0xd8, 0xa9, 0xfe, 0x19, 0xbc, 0x28, 0x93, 0xf0, 0x51, 0xe0, 0x82, 0xa9, 0x21, 0xeb, 0x30, 0x2b, + 0x7a, 0x6d, 0x26, 0x13, 0x70, 0x76, 0xe3, 0x95, 0x24, 0x70, 0x69, 0xbf, 0xd3, 0x6b, 0xb3, 0x8a, + 0x34, 0x25, 0x0b, 0x90, 0x73, 0xfc, 0x56, 0x95, 0xb9, 0xf2, 0xa5, 0x67, 0x2a, 0xf8, 0x9f, 0xfe, + 0xdb, 0x0c, 0x26, 0x1f, 0x03, 0x60, 0x92, 0xdf, 0x81, 0x53, 0x12, 0xc7, 0xb2, 0xeb, 0x98, 0xe6, + 0x8b, 0xa9, 0x51, 0xb6, 0xea, 0xc8, 0xfd, 0x85, 0xae, 0xfa, 0x97, 0x94, 0xe1, 0xcc, 0xa0, 0x8b, + 0x02, 0x08, 0x95, 0xdd, 0x2b, 0x71, 0x88, 0x48, 0xd3, 0x19, 0xdb, 0xe1, 0xef, 0x10, 0xad, 0xe0, + 0x45, 0xce, 0xc8, 0xe7, 0x90, 0x63, 0x1d, 0xdf, 0x16, 0x3d, 0x99, 0xd1, 0xc2, 0xe6, 0xfd, 0xc0, + 0xe6, 0xaf, 0xa7, 0xcb, 0x77, 0x1a, 0xb6, 0xd8, 0xf3, 0xab, 0x46, 0x8d, 0xb7, 0xcc, 0x78, 0x9b, + 0xdd, 0xbc, 0x51, 0xdb, 0xa3, 0xb6, 0x63, 0x86, 0x27, 0xf5, 0x20, 0x11, 0x9e, 0xb1, 0xcd, 0x5c, + 0x9b, 0x36, 0xed, 0x2f, 0x69, 0xb5, 0xc9, 0xb6, 0x1c, 0x51, 0x41, 0x5c, 0xb2, 0x0b, 0xa7, 0x6d, + 0xa7, 0xcb, 0x1c, 0xc1, 0xdd, 0xde, 0xd2, 0xec, 0x84, 0x83, 0x0c, 0xa0, 0xc9, 0x7d, 0x28, 0xa8, + 0xd4, 0x62, 0x87, 0xcc, 0xc9, 0xdc, 0x2c, 0xa7, 0xa6, 0x37, 0xd6, 0x1e, 0xf9, 0xee, 0xe0, 0x48, + 0xb7, 0xe0, 0x82, 0x2c, 0xdd, 0xdd, 0x66, 0x53, 0x5a, 0xf6, 0x47, 0x87, 0xdc, 0x03, 0x18, 0x0c, + 0x3c, 0xd6, 0xef, 0x8a, 0xa1, 0xd4, 0xc1, 0x08, 0xd4, 0xc1, 0x50, 0xf2, 0x83, 0xea, 0x60, 0x3c, + 0xa4, 0x0d, 0x86, 0xbe, 0x95, 0x88, 0xa7, 0xfe, 0x93, 0x06, 0x0b, 0xc3, 0x11, 0xb0, 0x41, 0xde, + 0x85, 0x9c, 0xa4, 0x12, 0x4c, 0xe1, 0xcc, 0x68, 0x6d, 0xfb, 0x93, 0x33, 0xdc, 0x58, 0x15, 0xf4, + 0x22, 0xef, 0xc7, 0x28, 0xaa, 0xfe, 0xb8, 0x7a, 0x22, 0x45, 0x04, 0x89, 0x72, 0xd4, 0xe1, 0xb2, + 0x0c, 0xf3, 0x01, 0x6b, 0x50, 0x89, 0xbd, 0xc3, 0x05, 0x6d, 0x6e, 0x07, 0xf2, 0x13, 0x4a, 0x09, + 0x83, 0x95, 0x31, 0x36, 0xf8, 0xa2, 0x3b, 0x50, 0x10, 0xc1, 0xb1, 0x25, 0xa5, 0xab, 0xaf, 0x2e, + 0x89, 0xc3, 0xf5, 0xa1, 0xdf, 0x42, 0xe7, 0xbc, 0x18, 0x20, 0xe9, 0x5f, 0x0c, 0x53, 0x79, 0xb0, + 0xef, 0x30, 0x37, 0x46, 0x65, 0xa8, 0x34, 0x33, 0xcf, 0x5d, 0x9a, 0x5f, 0xb4, 0xe1, 0x37, 0xc5, + 0x82, 0xe1, 0x9b, 0xee, 0x42, 0x81, 0x07, 0xc7, 0x83, 0x37, 0x05, 0xb5, 0x2a, 0x25, 0xaa, 0x51, + 0xe8, 0x5e, 0xc9, 0xf3, 0x01, 0xd4, 0xe4, 0x0a, 0x55, 0x87, 0xc5, 0x41, 0x3f, 0xc4, 0xa4, 0x7e, + 0x92, 0x7a, 0xf6, 0xb3, 0x06, 0x4b, 0xa3, 0x61, 0x26, 0xa2, 0x6a, 0xc3, 0x83, 0x3b, 0xfd, 0xdc, + 0x83, 0x7b, 0x00, 0xaf, 0xc6, 0x6b, 0xf7, 0xb1, 0x2d, 0xf6, 0xea, 0x2e, 0xdd, 0xa7, 0xcd, 0x2d, + 0x67, 0x97, 0xf7, 0xd3, 0x52, 0x06, 0xa2, 0xea, 0x66, 0x09, 0x6e, 0xed, 0xa3, 0x49, 0xa6, 0xbe, + 0xc4, 0xa0, 0xe7, 0x95, 0xfb, 0x0e, 0xef, 0xe3, 0x07, 0x72, 0xff, 0xda, 0xf8, 0xd0, 0x98, 0xaa, + 0xc9, 0xc7, 0x26, 0x5f, 0x69, 0xb0, 0xc8, 0x0e, 0xda, 0xac, 0x26, 0x58, 0x5d, 0xae, 0x5f, 0x66, + 0x75, 0x7c, 0xea, 0x08, 0x1f, 0x73, 0x39, 0x49, 0xbd, 0xbd, 0xd0, 0x0f, 0x14, 0x2c, 0x68, 0x56, + 0xc6, 0x30, 0xc4, 0x83, 0xf3, 0xad, 0xfe, 0xc3, 0xad, 0xff, 0x69, 0x9f, 0x9c, 0x0b, 0x23, 0xbc, + 0xa7, 0x16, 0xcb, 0xbd, 0x21, 0x61, 0x99, 0xcd, 0x9e, 0xc4, 0xa8, 0xbc, 0x6c, 0xfc, 0x7b, 0x0a, + 0xe6, 0x64, 0xed, 0xc8, 0x21, 0xe4, 0xf0, 0x8b, 0x23, 0x5d, 0x76, 0x63, 0x13, 0x56, 0xbc, 0x7a, + 0xa2, 0x9d, 0xaa, 0xbb, 0xae, 0x7f, 0xfd, 0xc7, 0x3f, 0x3f, 0x4c, 0x5f, 0x22, 0x45, 0x33, 0xf5, + 0xab, 0x8f, 0x7c, 0xa7, 0xc1, 0x9c, 0xec, 0x70, 0xf2, 0xfa, 0x49, 0xaa, 0xaf, 0xa2, 0x67, 0x5c, + 0x0e, 0xfa, 0xba, 0x0c, 0x7e, 0x8d, 0xac, 0x9a, 0x69, 0x5f, 0x8c, 0xe6, 0xa3, 0x20, 0xe9, 0x87, + 0xe6, 0x23, 0x35, 0xee, 0x87, 0xe4, 0x5b, 0x0d, 0x4e, 0x87, 0xdb, 0x89, 0xac, 0xa6, 0x06, 0x1a, + 0xde, 0x91, 0xc5, 0xb5, 0x2c, 0xa6, 0xc8, 0x6b, 0x45, 0xf2, 0xba, 0x48, 0x5e, 0x4e, 0xe5, 0x45, + 0x7e, 0xd5, 0x60, 0x3e, 0x69, 0xbd, 0x90, 0x9b, 0xa9, 0x71, 0xc6, 0x6c, 0xac, 0xe2, 0xad, 0x67, + 0xf4, 0x42, 0xa2, 0x1b, 0x92, 0xe8, 0x75, 0xb2, 0x96, 0x44, 0x34, 0xec, 0x4b, 0x33, 0xda, 0x8e, + 0x71, 0xe6, 0x91, 0x25, 0x92, 0x85, 0xf9, 0xe8, 0x82, 0xcb, 0xc2, 0x3c, 0x61, 0x53, 0x65, 0x65, + 0x1e, 0xdd, 0x66, 0xe4, 0x47, 0x0d, 0xf2, 0x11, 0xa5, 0x25, 0xd7, 0xc6, 0xb7, 0x59, 0x7c, 0x22, + 0xae, 0x67, 0x33, 0xce, 0x42, 0x4f, 0x8d, 0xc5, 0x48, 0x6b, 0xfe, 0xae, 0xc1, 0x62, 0x8a, 0xcc, + 0x92, 0xdb, 0x27, 0x67, 0x29, 0x71, 0x27, 0x14, 0xdf, 0x7a, 0x76, 0x47, 0x7c, 0xc2, 0x2d, 0xf9, + 0x04, 0x93, 0xdc, 0x18, 0x9f, 0xe1, 0xfd, 0xd0, 0xdb, 0xb2, 0x9d, 0x5d, 0xbe, 0x59, 0x7e, 0x7c, + 0x54, 0xd2, 0x9e, 0x1c, 0x95, 0xb4, 0xbf, 0x8f, 0x4a, 0xda, 0xf7, 0xc7, 0xa5, 0xa9, 0x27, 0xc7, + 0xa5, 0xa9, 0x3f, 0x8f, 0x4b, 0x53, 0x9f, 0xdc, 0xce, 0x2e, 0x95, 0x07, 0x18, 0x46, 0x2a, 0x66, + 0x35, 0x27, 0xcf, 0xdf, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x82, 0xa3, 0x58, 0x95, 0x18, 0x0f, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -740,6 +862,8 @@ type QueryClient interface { MegavaultOwnerShares(ctx context.Context, in *QueryMegavaultOwnerSharesRequest, opts ...grpc.CallOption) (*QueryMegavaultOwnerSharesResponse, error) // Queries vault params of a vault. VaultParams(ctx context.Context, in *QueryVaultParamsRequest, opts ...grpc.CallOption) (*QueryVaultParamsResponse, error) + // Queries withdrawal info for megavault. + MegavaultWithdrawalInfo(ctx context.Context, in *QueryMegavaultWithdrawalInfoRequest, opts ...grpc.CallOption) (*QueryMegavaultWithdrawalInfoResponse, error) } type queryClient struct { @@ -804,6 +928,15 @@ func (c *queryClient) VaultParams(ctx context.Context, in *QueryVaultParamsReque return out, nil } +func (c *queryClient) MegavaultWithdrawalInfo(ctx context.Context, in *QueryMegavaultWithdrawalInfoRequest, opts ...grpc.CallOption) (*QueryMegavaultWithdrawalInfoResponse, error) { + out := new(QueryMegavaultWithdrawalInfoResponse) + err := c.cc.Invoke(ctx, "/dydxprotocol.vault.Query/MegavaultWithdrawalInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Queries the Params. @@ -818,6 +951,8 @@ type QueryServer interface { MegavaultOwnerShares(context.Context, *QueryMegavaultOwnerSharesRequest) (*QueryMegavaultOwnerSharesResponse, error) // Queries vault params of a vault. VaultParams(context.Context, *QueryVaultParamsRequest) (*QueryVaultParamsResponse, error) + // Queries withdrawal info for megavault. + MegavaultWithdrawalInfo(context.Context, *QueryMegavaultWithdrawalInfoRequest) (*QueryMegavaultWithdrawalInfoResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -842,6 +977,9 @@ func (*UnimplementedQueryServer) MegavaultOwnerShares(ctx context.Context, req * func (*UnimplementedQueryServer) VaultParams(ctx context.Context, req *QueryVaultParamsRequest) (*QueryVaultParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VaultParams not implemented") } +func (*UnimplementedQueryServer) MegavaultWithdrawalInfo(ctx context.Context, req *QueryMegavaultWithdrawalInfoRequest) (*QueryMegavaultWithdrawalInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MegavaultWithdrawalInfo not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -955,6 +1093,24 @@ func _Query_VaultParams_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Query_MegavaultWithdrawalInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryMegavaultWithdrawalInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).MegavaultWithdrawalInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dydxprotocol.vault.Query/MegavaultWithdrawalInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).MegavaultWithdrawalInfo(ctx, req.(*QueryMegavaultWithdrawalInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "dydxprotocol.vault.Query", HandlerType: (*QueryServer)(nil), @@ -983,6 +1139,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "VaultParams", Handler: _Query_VaultParams_Handler, }, + { + MethodName: "MegavaultWithdrawalInfo", + Handler: _Query_MegavaultWithdrawalInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "dydxprotocol/vault/query.proto", @@ -1472,6 +1632,102 @@ func (m *QueryVaultParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *QueryMegavaultWithdrawalInfoRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMegavaultWithdrawalInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMegavaultWithdrawalInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.SharesToWithdraw.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryMegavaultWithdrawalInfoResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMegavaultWithdrawalInfoResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMegavaultWithdrawalInfoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.TotalShares.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.MegavaultEquity.Size() + i -= size + if _, err := m.MegavaultEquity.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.ExpectedQuoteQuantums.Size() + i -= size + if _, err := m.ExpectedQuoteQuantums.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.SharesToWithdraw.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -1655,6 +1911,34 @@ func (m *QueryVaultParamsResponse) Size() (n int) { return n } +func (m *QueryMegavaultWithdrawalInfoRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.SharesToWithdraw.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryMegavaultWithdrawalInfoResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.SharesToWithdraw.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.ExpectedQuoteQuantums.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.MegavaultEquity.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.TotalShares.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2915,6 +3199,271 @@ func (m *QueryVaultParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryMegavaultWithdrawalInfoRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMegavaultWithdrawalInfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMegavaultWithdrawalInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SharesToWithdraw", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SharesToWithdraw.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryMegavaultWithdrawalInfoResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMegavaultWithdrawalInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMegavaultWithdrawalInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SharesToWithdraw", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SharesToWithdraw.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpectedQuoteQuantums", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExpectedQuoteQuantums.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MegavaultEquity", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MegavaultEquity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalShares", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TotalShares.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/protocol/x/vault/types/query.pb.gw.go b/protocol/x/vault/types/query.pb.gw.go index 332ed011bd..87c4c5c0a8 100644 --- a/protocol/x/vault/types/query.pb.gw.go +++ b/protocol/x/vault/types/query.pb.gw.go @@ -305,6 +305,42 @@ func local_request_Query_VaultParams_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Query_MegavaultWithdrawalInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_MegavaultWithdrawalInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultWithdrawalInfoRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultWithdrawalInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.MegavaultWithdrawalInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_MegavaultWithdrawalInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultWithdrawalInfoRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultWithdrawalInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.MegavaultWithdrawalInfo(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -449,6 +485,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_MegavaultWithdrawalInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_MegavaultWithdrawalInfo_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MegavaultWithdrawalInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -610,6 +669,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_MegavaultWithdrawalInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_MegavaultWithdrawalInfo_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MegavaultWithdrawalInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -625,6 +704,8 @@ var ( pattern_Query_MegavaultOwnerShares_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"dydxprotocol", "vault", "megavault", "owner_shares"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_VaultParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"dydxprotocol", "vault", "params", "type", "number"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_MegavaultWithdrawalInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"dydxprotocol", "vault", "megavault", "withdrawal_info"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -639,4 +720,6 @@ var ( forward_Query_MegavaultOwnerShares_0 = runtime.ForwardResponseMessage forward_Query_VaultParams_0 = runtime.ForwardResponseMessage + + forward_Query_MegavaultWithdrawalInfo_0 = runtime.ForwardResponseMessage ) From 79db31a4e730f05a8b4cf737db1ac038af599ce9 Mon Sep 17 00:00:00 2001 From: sr33j Date: Mon, 23 Sep 2024 16:28:37 -0400 Subject: [PATCH 02/10] add check for invalid skew factor (#2249) --- protocol/x/vault/types/errors.go | 5 ++++ protocol/x/vault/types/params.go | 9 +++++++ protocol/x/vault/types/params_test.go | 37 +++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/protocol/x/vault/types/errors.go b/protocol/x/vault/types/errors.go index 4b4d541dec..3374cd11fd 100644 --- a/protocol/x/vault/types/errors.go +++ b/protocol/x/vault/types/errors.go @@ -155,4 +155,9 @@ var ( 30, "Shares must be positive", ) + ErrInvalidSkewFactor = errorsmod.Register( + ModuleName, + 31, + "Skew factor times order_size_pct must be less than 2 to avoid skewing over the spread", + ) ) diff --git a/protocol/x/vault/types/params.go b/protocol/x/vault/types/params.go index 4236d981d1..578f7030cb 100644 --- a/protocol/x/vault/types/params.go +++ b/protocol/x/vault/types/params.go @@ -2,6 +2,7 @@ package types import ( "math" + "math/big" "github.com/dydxprotocol/v4-chain/protocol/dtypes" "github.com/dydxprotocol/v4-chain/protocol/lib" @@ -42,6 +43,14 @@ func (p QuotingParams) Validate() error { if p.ActivationThresholdQuoteQuantums.Sign() < 0 { return ErrInvalidActivationThresholdQuoteQuantums } + // Skew factor times order_size_pct must be less than 2 to avoid skewing over the spread + skewFactor := new(big.Int).SetUint64(uint64(p.SkewFactorPpm)) + orderSizePct := new(big.Int).SetUint64(uint64(p.OrderSizePctPpm)) + skewFactorOrderSizePctProduct := new(big.Int).Mul(skewFactor, orderSizePct) + skewFactorOrderSizePctProductThreshold := big.NewInt(2_000_000 * 1_000_000) + if skewFactorOrderSizePctProduct.Cmp(skewFactorOrderSizePctProductThreshold) >= 0 { + return ErrInvalidSkewFactor + } return nil } diff --git a/protocol/x/vault/types/params_test.go b/protocol/x/vault/types/params_test.go index 9705241f61..4d72dd9d5f 100644 --- a/protocol/x/vault/types/params_test.go +++ b/protocol/x/vault/types/params_test.go @@ -1,6 +1,7 @@ package types_test import ( + "math" "testing" "github.com/dydxprotocol/v4-chain/protocol/dtypes" @@ -80,6 +81,42 @@ func TestValidateQuotingParams(t *testing.T) { }, expectedErr: types.ErrInvalidActivationThresholdQuoteQuantums, }, + "Failure - SkewFactorPpm is high. Product of SkewFactorPpm and OrderSizePctPpm is above threshold.": { + params: types.QuotingParams{ + Layers: 2, + SpreadMinPpm: 3_000, + SpreadBufferPpm: 1_500, + SkewFactorPpm: 20_000_000, + OrderSizePctPpm: 100_000, + OrderExpirationSeconds: 5, + ActivationThresholdQuoteQuantums: dtypes.NewInt(1), + }, + expectedErr: types.ErrInvalidSkewFactor, + }, + "Failure - OrderSizePctPpm is high. Product of SkewFactorPpm and OrderSizePctPpm is above threshold.": { + params: types.QuotingParams{ + Layers: 2, + SpreadMinPpm: 3_000, + SpreadBufferPpm: 1_500, + SkewFactorPpm: 2_000_000, + OrderSizePctPpm: 1_000_000, + OrderExpirationSeconds: 5, + ActivationThresholdQuoteQuantums: dtypes.NewInt(1), + }, + expectedErr: types.ErrInvalidSkewFactor, + }, + "Failure - Both OrderSizePctPpm and SkewFactorPpm are MaxUint32. The product is above the threshold.": { + params: types.QuotingParams{ + Layers: 2, + SpreadMinPpm: 3_000, + SpreadBufferPpm: 1_500, + SkewFactorPpm: math.MaxUint32, + OrderSizePctPpm: math.MaxUint32, + OrderExpirationSeconds: 5, + ActivationThresholdQuoteQuantums: dtypes.NewInt(1), + }, + expectedErr: types.ErrInvalidSkewFactor, + }, } for name, tc := range tests { From 0601febbcd265261f3e1cac55681587156cba7bc Mon Sep 17 00:00:00 2001 From: Tian Date: Mon, 23 Sep 2024 16:51:34 -0400 Subject: [PATCH 03/10] add megavault owner shares query (#2323) --- .../codegen/dydxprotocol/vault/query.lcd.ts | 18 +- .../dydxprotocol/vault/query.rpc.Query.ts | 26 +- .../src/codegen/dydxprotocol/vault/query.ts | 228 ++++- proto/dydxprotocol/vault/query.proto | 44 +- protocol/x/vault/client/cli/query.go | 32 +- protocol/x/vault/keeper/grpc_query_shares.go | 55 +- .../x/vault/keeper/grpc_query_shares_test.go | 188 ++++- protocol/x/vault/types/query.pb.go | 786 ++++++++++++++++-- protocol/x/vault/types/query.pb.gw.go | 121 ++- 9 files changed, 1359 insertions(+), 139 deletions(-) diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts index 9350c68ecf..bde998565a 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.lcd.ts @@ -1,6 +1,6 @@ import { setPaginationParams } from "../../helpers"; import { LCDClient } from "@osmonauts/lcd"; -import { QueryParamsRequest, QueryParamsResponseSDKType, QueryVaultRequest, QueryVaultResponseSDKType, QueryAllVaultsRequest, QueryAllVaultsResponseSDKType, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponseSDKType, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponseSDKType, QueryVaultParamsRequest, QueryVaultParamsResponseSDKType, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponseSDKType } from "./query"; +import { QueryParamsRequest, QueryParamsResponseSDKType, QueryVaultRequest, QueryVaultResponseSDKType, QueryAllVaultsRequest, QueryAllVaultsResponseSDKType, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponseSDKType, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponseSDKType, QueryMegavaultAllOwnerSharesRequest, QueryMegavaultAllOwnerSharesResponseSDKType, QueryVaultParamsRequest, QueryVaultParamsResponseSDKType, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponseSDKType } from "./query"; export class LCDQueryClient { req: LCDClient; @@ -15,6 +15,7 @@ export class LCDQueryClient { this.allVaults = this.allVaults.bind(this); this.megavaultTotalShares = this.megavaultTotalShares.bind(this); this.megavaultOwnerShares = this.megavaultOwnerShares.bind(this); + this.megavaultAllOwnerShares = this.megavaultAllOwnerShares.bind(this); this.vaultParams = this.vaultParams.bind(this); this.megavaultWithdrawalInfo = this.megavaultWithdrawalInfo.bind(this); } @@ -59,9 +60,16 @@ export class LCDQueryClient { /* Queries owner shares of megavault. */ - async megavaultOwnerShares(params: QueryMegavaultOwnerSharesRequest = { + async megavaultOwnerShares(params: QueryMegavaultOwnerSharesRequest): Promise { + const endpoint = `dydxprotocol/vault/megavault/owner_shares/${params.address}`; + return await this.req.get(endpoint); + } + /* Queries all owner shares of megavault. */ + + + async megavaultAllOwnerShares(params: QueryMegavaultAllOwnerSharesRequest = { pagination: undefined - }): Promise { + }): Promise { const options: any = { params: {} }; @@ -70,8 +78,8 @@ export class LCDQueryClient { setPaginationParams(options, params.pagination); } - const endpoint = `dydxprotocol/vault/megavault/owner_shares`; - return await this.req.get(endpoint, options); + const endpoint = `dydxprotocol/vault/megavault/all_owner_shares`; + return await this.req.get(endpoint, options); } /* Queries vault params of a vault. */ diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts index a77656dc6c..7889700975 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.rpc.Query.ts @@ -1,7 +1,7 @@ import { Rpc } from "../../helpers"; import * as _m0 from "protobufjs/minimal"; import { QueryClient, createProtobufRpcClient } from "@cosmjs/stargate"; -import { QueryParamsRequest, QueryParamsResponse, QueryVaultRequest, QueryVaultResponse, QueryAllVaultsRequest, QueryAllVaultsResponse, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponse, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponse, QueryVaultParamsRequest, QueryVaultParamsResponse, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponse } from "./query"; +import { QueryParamsRequest, QueryParamsResponse, QueryVaultRequest, QueryVaultResponse, QueryAllVaultsRequest, QueryAllVaultsResponse, QueryMegavaultTotalSharesRequest, QueryMegavaultTotalSharesResponse, QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponse, QueryMegavaultAllOwnerSharesRequest, QueryMegavaultAllOwnerSharesResponse, QueryVaultParamsRequest, QueryVaultParamsResponse, QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponse } from "./query"; /** Query defines the gRPC querier service. */ export interface Query { @@ -18,7 +18,10 @@ export interface Query { megavaultTotalShares(request?: QueryMegavaultTotalSharesRequest): Promise; /** Queries owner shares of megavault. */ - megavaultOwnerShares(request?: QueryMegavaultOwnerSharesRequest): Promise; + megavaultOwnerShares(request: QueryMegavaultOwnerSharesRequest): Promise; + /** Queries all owner shares of megavault. */ + + megavaultAllOwnerShares(request?: QueryMegavaultAllOwnerSharesRequest): Promise; /** Queries vault params of a vault. */ vaultParams(request: QueryVaultParamsRequest): Promise; @@ -36,6 +39,7 @@ export class QueryClientImpl implements Query { this.allVaults = this.allVaults.bind(this); this.megavaultTotalShares = this.megavaultTotalShares.bind(this); this.megavaultOwnerShares = this.megavaultOwnerShares.bind(this); + this.megavaultAllOwnerShares = this.megavaultAllOwnerShares.bind(this); this.vaultParams = this.vaultParams.bind(this); this.megavaultWithdrawalInfo = this.megavaultWithdrawalInfo.bind(this); } @@ -66,14 +70,20 @@ export class QueryClientImpl implements Query { return promise.then(data => QueryMegavaultTotalSharesResponse.decode(new _m0.Reader(data))); } - megavaultOwnerShares(request: QueryMegavaultOwnerSharesRequest = { - pagination: undefined - }): Promise { + megavaultOwnerShares(request: QueryMegavaultOwnerSharesRequest): Promise { const data = QueryMegavaultOwnerSharesRequest.encode(request).finish(); const promise = this.rpc.request("dydxprotocol.vault.Query", "MegavaultOwnerShares", data); return promise.then(data => QueryMegavaultOwnerSharesResponse.decode(new _m0.Reader(data))); } + megavaultAllOwnerShares(request: QueryMegavaultAllOwnerSharesRequest = { + pagination: undefined + }): Promise { + const data = QueryMegavaultAllOwnerSharesRequest.encode(request).finish(); + const promise = this.rpc.request("dydxprotocol.vault.Query", "MegavaultAllOwnerShares", data); + return promise.then(data => QueryMegavaultAllOwnerSharesResponse.decode(new _m0.Reader(data))); + } + vaultParams(request: QueryVaultParamsRequest): Promise { const data = QueryVaultParamsRequest.encode(request).finish(); const promise = this.rpc.request("dydxprotocol.vault.Query", "VaultParams", data); @@ -107,10 +117,14 @@ export const createRpcQueryExtension = (base: QueryClient) => { return queryService.megavaultTotalShares(request); }, - megavaultOwnerShares(request?: QueryMegavaultOwnerSharesRequest): Promise { + megavaultOwnerShares(request: QueryMegavaultOwnerSharesRequest): Promise { return queryService.megavaultOwnerShares(request); }, + megavaultAllOwnerShares(request?: QueryMegavaultAllOwnerSharesRequest): Promise { + return queryService.megavaultAllOwnerShares(request); + }, + vaultParams(request: QueryVaultParamsRequest): Promise { return queryService.vaultParams(request); }, diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts index 2a62eebecc..54219e8514 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/vault/query.ts @@ -1,6 +1,6 @@ import { VaultType, VaultTypeSDKType, VaultId, VaultIdSDKType } from "./vault"; import { PageRequest, PageRequestSDKType, PageResponse, PageResponseSDKType } from "../../cosmos/base/query/v1beta1/pagination"; -import { NumShares, NumSharesSDKType, OwnerShare, OwnerShareSDKType } from "./share"; +import { NumShares, NumSharesSDKType, ShareUnlock, ShareUnlockSDKType, OwnerShare, OwnerShareSDKType } from "./share"; import { Params, ParamsSDKType, QuotingParams, QuotingParamsSDKType, OperatorParams, OperatorParamsSDKType, VaultParams, VaultParamsSDKType } from "./params"; import { SubaccountId, SubaccountIdSDKType } from "../subaccounts/subaccount"; import * as _m0 from "protobufjs/minimal"; @@ -125,7 +125,7 @@ export interface QueryMegavaultTotalSharesResponseSDKType { */ export interface QueryMegavaultOwnerSharesRequest { - pagination?: PageRequest; + address: string; } /** * QueryMegavaultOwnerSharesRequest is a request type for the @@ -133,7 +133,7 @@ export interface QueryMegavaultOwnerSharesRequest { */ export interface QueryMegavaultOwnerSharesRequestSDKType { - pagination?: PageRequestSDKType; + address: string; } /** * QueryMegavaultOwnerSharesResponse is a response type for the @@ -141,8 +141,23 @@ export interface QueryMegavaultOwnerSharesRequestSDKType { */ export interface QueryMegavaultOwnerSharesResponse { - ownerShares: OwnerShare[]; - pagination?: PageResponse; + /** Owner address. */ + address: string; + /** Total number of shares that belong to the owner. */ + + shares?: NumShares; + /** All share unlocks. */ + + shareUnlocks: ShareUnlock[]; + /** Owner equity in megavault (in quote quantums). */ + + equity: Uint8Array; + /** + * Equity that owner can withdraw in quote quantums (as one cannot + * withdraw locked shares). + */ + + withdrawableEquity: Uint8Array; } /** * QueryMegavaultOwnerSharesResponse is a response type for the @@ -150,6 +165,55 @@ export interface QueryMegavaultOwnerSharesResponse { */ export interface QueryMegavaultOwnerSharesResponseSDKType { + /** Owner address. */ + address: string; + /** Total number of shares that belong to the owner. */ + + shares?: NumSharesSDKType; + /** All share unlocks. */ + + share_unlocks: ShareUnlockSDKType[]; + /** Owner equity in megavault (in quote quantums). */ + + equity: Uint8Array; + /** + * Equity that owner can withdraw in quote quantums (as one cannot + * withdraw locked shares). + */ + + withdrawable_equity: Uint8Array; +} +/** + * QueryMegavaultAllOwnerSharesRequest is a request type for the + * MegavaultAllOwnerShares RPC method. + */ + +export interface QueryMegavaultAllOwnerSharesRequest { + pagination?: PageRequest; +} +/** + * QueryMegavaultAllOwnerSharesRequest is a request type for the + * MegavaultAllOwnerShares RPC method. + */ + +export interface QueryMegavaultAllOwnerSharesRequestSDKType { + pagination?: PageRequestSDKType; +} +/** + * QueryMegavaultAllOwnerSharesResponse is a response type for the + * MegavaultAllOwnerShares RPC method. + */ + +export interface QueryMegavaultAllOwnerSharesResponse { + ownerShares: OwnerShare[]; + pagination?: PageResponse; +} +/** + * QueryMegavaultAllOwnerSharesResponse is a response type for the + * MegavaultAllOwnerShares RPC method. + */ + +export interface QueryMegavaultAllOwnerSharesResponseSDKType { owner_shares: OwnerShareSDKType[]; pagination?: PageResponseSDKType; } @@ -662,14 +726,14 @@ export const QueryMegavaultTotalSharesResponse = { function createBaseQueryMegavaultOwnerSharesRequest(): QueryMegavaultOwnerSharesRequest { return { - pagination: undefined + address: "" }; } export const QueryMegavaultOwnerSharesRequest = { encode(message: QueryMegavaultOwnerSharesRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.pagination !== undefined) { - PageRequest.encode(message.pagination, writer.uint32(26).fork()).ldelim(); + if (message.address !== "") { + writer.uint32(10).string(message.address); } return writer; @@ -684,8 +748,8 @@ export const QueryMegavaultOwnerSharesRequest = { const tag = reader.uint32(); switch (tag >>> 3) { - case 3: - message.pagination = PageRequest.decode(reader, reader.uint32()); + case 1: + message.address = reader.string(); break; default: @@ -699,7 +763,7 @@ export const QueryMegavaultOwnerSharesRequest = { fromPartial(object: DeepPartial): QueryMegavaultOwnerSharesRequest { const message = createBaseQueryMegavaultOwnerSharesRequest(); - message.pagination = object.pagination !== undefined && object.pagination !== null ? PageRequest.fromPartial(object.pagination) : undefined; + message.address = object.address ?? ""; return message; } @@ -707,13 +771,143 @@ export const QueryMegavaultOwnerSharesRequest = { function createBaseQueryMegavaultOwnerSharesResponse(): QueryMegavaultOwnerSharesResponse { return { - ownerShares: [], - pagination: undefined + address: "", + shares: undefined, + shareUnlocks: [], + equity: new Uint8Array(), + withdrawableEquity: new Uint8Array() }; } export const QueryMegavaultOwnerSharesResponse = { encode(message: QueryMegavaultOwnerSharesResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.address !== "") { + writer.uint32(10).string(message.address); + } + + if (message.shares !== undefined) { + NumShares.encode(message.shares, writer.uint32(18).fork()).ldelim(); + } + + for (const v of message.shareUnlocks) { + ShareUnlock.encode(v!, writer.uint32(26).fork()).ldelim(); + } + + if (message.equity.length !== 0) { + writer.uint32(34).bytes(message.equity); + } + + if (message.withdrawableEquity.length !== 0) { + writer.uint32(42).bytes(message.withdrawableEquity); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultOwnerSharesResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryMegavaultOwnerSharesResponse(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.address = reader.string(); + break; + + case 2: + message.shares = NumShares.decode(reader, reader.uint32()); + break; + + case 3: + message.shareUnlocks.push(ShareUnlock.decode(reader, reader.uint32())); + break; + + case 4: + message.equity = reader.bytes(); + break; + + case 5: + message.withdrawableEquity = reader.bytes(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryMegavaultOwnerSharesResponse { + const message = createBaseQueryMegavaultOwnerSharesResponse(); + message.address = object.address ?? ""; + message.shares = object.shares !== undefined && object.shares !== null ? NumShares.fromPartial(object.shares) : undefined; + message.shareUnlocks = object.shareUnlocks?.map(e => ShareUnlock.fromPartial(e)) || []; + message.equity = object.equity ?? new Uint8Array(); + message.withdrawableEquity = object.withdrawableEquity ?? new Uint8Array(); + return message; + } + +}; + +function createBaseQueryMegavaultAllOwnerSharesRequest(): QueryMegavaultAllOwnerSharesRequest { + return { + pagination: undefined + }; +} + +export const QueryMegavaultAllOwnerSharesRequest = { + encode(message: QueryMegavaultAllOwnerSharesRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.pagination !== undefined) { + PageRequest.encode(message.pagination, writer.uint32(10).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultAllOwnerSharesRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryMegavaultAllOwnerSharesRequest(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.pagination = PageRequest.decode(reader, reader.uint32()); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryMegavaultAllOwnerSharesRequest { + const message = createBaseQueryMegavaultAllOwnerSharesRequest(); + message.pagination = object.pagination !== undefined && object.pagination !== null ? PageRequest.fromPartial(object.pagination) : undefined; + return message; + } + +}; + +function createBaseQueryMegavaultAllOwnerSharesResponse(): QueryMegavaultAllOwnerSharesResponse { + return { + ownerShares: [], + pagination: undefined + }; +} + +export const QueryMegavaultAllOwnerSharesResponse = { + encode(message: QueryMegavaultAllOwnerSharesResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { for (const v of message.ownerShares) { OwnerShare.encode(v!, writer.uint32(10).fork()).ldelim(); } @@ -725,10 +919,10 @@ export const QueryMegavaultOwnerSharesResponse = { return writer; }, - decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultOwnerSharesResponse { + decode(input: _m0.Reader | Uint8Array, length?: number): QueryMegavaultAllOwnerSharesResponse { const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseQueryMegavaultOwnerSharesResponse(); + const message = createBaseQueryMegavaultAllOwnerSharesResponse(); while (reader.pos < end) { const tag = reader.uint32(); @@ -751,8 +945,8 @@ export const QueryMegavaultOwnerSharesResponse = { return message; }, - fromPartial(object: DeepPartial): QueryMegavaultOwnerSharesResponse { - const message = createBaseQueryMegavaultOwnerSharesResponse(); + fromPartial(object: DeepPartial): QueryMegavaultAllOwnerSharesResponse { + const message = createBaseQueryMegavaultAllOwnerSharesResponse(); message.ownerShares = object.ownerShares?.map(e => OwnerShare.fromPartial(e)) || []; message.pagination = object.pagination !== undefined && object.pagination !== null ? PageResponse.fromPartial(object.pagination) : undefined; return message; diff --git a/proto/dydxprotocol/vault/query.proto b/proto/dydxprotocol/vault/query.proto index faff37c692..1c686d1262 100644 --- a/proto/dydxprotocol/vault/query.proto +++ b/proto/dydxprotocol/vault/query.proto @@ -1,9 +1,10 @@ syntax = "proto3"; package dydxprotocol.vault; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; -import "cosmos/base/query/v1beta1/pagination.proto"; import "dydxprotocol/subaccounts/subaccount.proto"; import "dydxprotocol/vault/params.proto"; import "dydxprotocol/vault/share.proto"; @@ -33,7 +34,14 @@ service Query { // Queries owner shares of megavault. rpc MegavaultOwnerShares(QueryMegavaultOwnerSharesRequest) returns (QueryMegavaultOwnerSharesResponse) { - option (google.api.http).get = "/dydxprotocol/vault/megavault/owner_shares"; + option (google.api.http).get = + "/dydxprotocol/vault/megavault/owner_shares/{address}"; + } + // Queries all owner shares of megavault. + rpc MegavaultAllOwnerShares(QueryMegavaultAllOwnerSharesRequest) + returns (QueryMegavaultAllOwnerSharesResponse) { + option (google.api.http).get = + "/dydxprotocol/vault/megavault/all_owner_shares"; } // Queries vault params of a vault. rpc VaultParams(QueryVaultParamsRequest) returns (QueryVaultParamsResponse) { @@ -105,12 +113,42 @@ message QueryMegavaultTotalSharesResponse { NumShares total_shares = 1; } // QueryMegavaultOwnerSharesRequest is a request type for the // MegavaultOwnerShares RPC method. message QueryMegavaultOwnerSharesRequest { - cosmos.base.query.v1beta1.PageRequest pagination = 3; + string address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; } // QueryMegavaultOwnerSharesResponse is a response type for the // MegavaultOwnerShares RPC method. message QueryMegavaultOwnerSharesResponse { + // Owner address. + string address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + // Total number of shares that belong to the owner. + NumShares shares = 2 [ (gogoproto.nullable) = false ]; + // All share unlocks. + repeated ShareUnlock share_unlocks = 3 [ (gogoproto.nullable) = false ]; + // Owner equity in megavault (in quote quantums). + bytes equity = 4 [ + (gogoproto.customtype) = + "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt", + (gogoproto.nullable) = false + ]; + // Equity that owner can withdraw in quote quantums (as one cannot + // withdraw locked shares). + bytes withdrawable_equity = 5 [ + (gogoproto.customtype) = + "github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt", + (gogoproto.nullable) = false + ]; +} + +// QueryMegavaultAllOwnerSharesRequest is a request type for the +// MegavaultAllOwnerShares RPC method. +message QueryMegavaultAllOwnerSharesRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryMegavaultAllOwnerSharesResponse is a response type for the +// MegavaultAllOwnerShares RPC method. +message QueryMegavaultAllOwnerSharesResponse { repeated OwnerShare owner_shares = 1; cosmos.base.query.v1beta1.PageResponse pagination = 2; } diff --git a/protocol/x/vault/client/cli/query.go b/protocol/x/vault/client/cli/query.go index 93b2c5a115..ad9c2b24e9 100644 --- a/protocol/x/vault/client/cli/query.go +++ b/protocol/x/vault/client/cli/query.go @@ -30,6 +30,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdQueryTotalShares()) cmd.AddCommand(CmdQueryListOwnerShares()) cmd.AddCommand(CmdQueryMegavaultWithdrawalInfo()) + cmd.AddCommand(CmdQueryOwnerShares()) return cmd } @@ -169,11 +170,11 @@ func CmdQueryListOwnerShares() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) - request := &types.QueryMegavaultOwnerSharesRequest{ + request := &types.QueryMegavaultAllOwnerSharesRequest{ Pagination: pageReq, } - res, err := queryClient.MegavaultOwnerShares(context.Background(), request) + res, err := queryClient.MegavaultAllOwnerShares(context.Background(), request) if err != nil { return err } @@ -221,3 +222,30 @@ func CmdQueryMegavaultWithdrawalInfo() *cobra.Command { return cmd } + +func CmdQueryOwnerShares() *cobra.Command { + cmd := &cobra.Command{ + Use: "owner-shares [address]", + Short: "get owner shares by their address", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.MegavaultOwnerShares( + context.Background(), + &types.QueryMegavaultOwnerSharesRequest{ + Address: args[0], + }, + ) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/protocol/x/vault/keeper/grpc_query_shares.go b/protocol/x/vault/keeper/grpc_query_shares.go index edd51e2c1a..28564ace6e 100644 --- a/protocol/x/vault/keeper/grpc_query_shares.go +++ b/protocol/x/vault/keeper/grpc_query_shares.go @@ -2,11 +2,13 @@ package keeper import ( "context" + "math/big" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/dydxprotocol/v4-chain/protocol/dtypes" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -33,6 +35,57 @@ func (k Keeper) MegavaultOwnerShares( } ctx := lib.UnwrapSDKContext(c, types.ModuleName) + ownerShares, exists := k.GetOwnerShares(ctx, req.Address) + if !exists { + return nil, status.Error(codes.NotFound, "owner not found") + } + if ownerShares.NumShares.Sign() < 0 { + return nil, status.Error(codes.Internal, "owner has negative shares") + } else if ownerShares.NumShares.Sign() == 0 { + return &types.QueryMegavaultOwnerSharesResponse{ + Address: req.Address, + Shares: ownerShares, + }, nil + } + + shareUnlocks, exists := k.GetOwnerShareUnlocks(ctx, req.Address) + totalLockedShares := big.NewInt(0) + if exists { + totalLockedShares = shareUnlocks.GetTotalLockedShares() + } + + megavaultEquity, err := k.GetMegavaultEquity(ctx) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + totalShares := k.GetTotalShares(ctx) + + bigOwnerShares := ownerShares.NumShares.BigInt() + ownerEquity := new(big.Int).Mul(bigOwnerShares, megavaultEquity) + ownerEquity.Quo(ownerEquity, totalShares.NumShares.BigInt()) + + ownerWithdrawableEquity := new(big.Int).Sub(bigOwnerShares, totalLockedShares) + ownerWithdrawableEquity.Mul(ownerWithdrawableEquity, ownerEquity) + ownerWithdrawableEquity.Quo(ownerWithdrawableEquity, bigOwnerShares) + + return &types.QueryMegavaultOwnerSharesResponse{ + Address: req.Address, + Shares: ownerShares, + ShareUnlocks: shareUnlocks.ShareUnlocks, + Equity: dtypes.NewIntFromBigInt(ownerEquity), + WithdrawableEquity: dtypes.NewIntFromBigInt(ownerWithdrawableEquity), + }, nil +} + +func (k Keeper) MegavaultAllOwnerShares( + c context.Context, + req *types.QueryMegavaultAllOwnerSharesRequest, +) (*types.QueryMegavaultAllOwnerSharesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := lib.UnwrapSDKContext(c, types.ModuleName) + var ownerShares []*types.OwnerShare ownerSharesStore := k.getOwnerSharesStore(ctx) pageRes, err := query.Paginate(ownerSharesStore, req.Pagination, func(key []byte, value []byte) error { @@ -53,7 +106,7 @@ func (k Keeper) MegavaultOwnerShares( return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryMegavaultOwnerSharesResponse{ + return &types.QueryMegavaultAllOwnerSharesResponse{ OwnerShares: ownerShares, Pagination: pageRes, }, nil diff --git a/protocol/x/vault/keeper/grpc_query_shares_test.go b/protocol/x/vault/keeper/grpc_query_shares_test.go index 0eb32db72e..fdb207507e 100644 --- a/protocol/x/vault/keeper/grpc_query_shares_test.go +++ b/protocol/x/vault/keeper/grpc_query_shares_test.go @@ -4,19 +4,21 @@ import ( "math/big" "testing" + "github.com/cometbft/cometbft/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/dydxprotocol/v4-chain/protocol/dtypes" testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" vaulttypes "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" "github.com/stretchr/testify/require" ) -func TestMegavaultOwnerShares(t *testing.T) { +func TestMegavaultAllOwnerShares(t *testing.T) { tests := map[string]struct { /* --- Setup --- */ // Request. - req *vaulttypes.QueryMegavaultOwnerSharesRequest + req *vaulttypes.QueryMegavaultAllOwnerSharesRequest // Owner shares. ownerShares map[string]*big.Int @@ -25,7 +27,7 @@ func TestMegavaultOwnerShares(t *testing.T) { expectedErr string }{ "Success": { - req: &vaulttypes.QueryMegavaultOwnerSharesRequest{}, + req: &vaulttypes.QueryMegavaultAllOwnerSharesRequest{}, ownerShares: map[string]*big.Int{ constants.Alice_Num0.Owner: big.NewInt(100), constants.Bob_Num0.Owner: big.NewInt(200), @@ -46,7 +48,7 @@ func TestMegavaultOwnerShares(t *testing.T) { }, }, "Success: no owners": { - req: &vaulttypes.QueryMegavaultOwnerSharesRequest{}, + req: &vaulttypes.QueryMegavaultAllOwnerSharesRequest{}, ownerShares: map[string]*big.Int{}, }, "Error: nil request": { @@ -72,7 +74,7 @@ func TestMegavaultOwnerShares(t *testing.T) { require.NoError(t, err) // Check OwnerShares query response is as expected. - response, err := k.MegavaultOwnerShares(ctx, tc.req) + response, err := k.MegavaultAllOwnerShares(ctx, tc.req) if tc.expectedErr != "" { require.ErrorContains(t, err, tc.expectedErr) } else { @@ -94,3 +96,179 @@ func TestMegavaultOwnerShares(t *testing.T) { }) } } + +func TestMegavaultOwnerShares(t *testing.T) { + tests := map[string]struct { + /* --- Setup --- */ + // Request. + req *vaulttypes.QueryMegavaultOwnerSharesRequest + // Owner address. + ownerAddress string + // Owner shares. + ownerShares *big.Int + // Share unlocks. + shareUnlocks []vaulttypes.ShareUnlock + // Total shares. + totalShares *big.Int + // Megavault equity. + megavaultEquity *big.Int + + /* --- Expectations --- */ + expectedOwnerEquity *big.Int + expectedOwnerWithdrawableEquity *big.Int + expectedErr string + }{ + "Success with zero unlock": { + req: &vaulttypes.QueryMegavaultOwnerSharesRequest{ + Address: constants.AliceAccAddress.String(), + }, + ownerAddress: constants.AliceAccAddress.String(), + ownerShares: big.NewInt(100), + totalShares: big.NewInt(5_000), + megavaultEquity: big.NewInt(2_000_000), + expectedOwnerEquity: big.NewInt(40_000), + expectedOwnerWithdrawableEquity: big.NewInt(40_000), + }, + "Success with one unlock": { + req: &vaulttypes.QueryMegavaultOwnerSharesRequest{ + Address: constants.AliceAccAddress.String(), + }, + ownerAddress: constants.AliceAccAddress.String(), + ownerShares: big.NewInt(100), + shareUnlocks: []vaulttypes.ShareUnlock{ + { + Shares: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(17), + }, + UnlockBlockHeight: 123, + }, + }, + totalShares: big.NewInt(5_000), + megavaultEquity: big.NewInt(2_000_000), + expectedOwnerEquity: big.NewInt(40_000), + // 40_000 * (100 - 17) / 100 = 33_200 + expectedOwnerWithdrawableEquity: big.NewInt(33_200), + }, + "Success with two unlocks": { + req: &vaulttypes.QueryMegavaultOwnerSharesRequest{ + Address: constants.BobAccAddress.String(), + }, + ownerAddress: constants.BobAccAddress.String(), + ownerShares: big.NewInt(47_123), + shareUnlocks: []vaulttypes.ShareUnlock{ + { + Shares: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(1_234), + }, + UnlockBlockHeight: 905, + }, + { + Shares: vaulttypes.NumShares{ + NumShares: dtypes.NewInt(4_444), + }, + UnlockBlockHeight: 1023, + }, + }, + totalShares: big.NewInt(358_791_341), + megavaultEquity: big.NewInt(753_582_314_912), + // 753_582_314_912 * 47_123 / 358_791_341 ~= 98_974_126 + expectedOwnerEquity: big.NewInt(98_974_126), + // 98_974_126 * (47_123 - 5_678) / 47_123 ~= 87_048_419 + expectedOwnerWithdrawableEquity: big.NewInt(87_048_419), + }, + "Success: owner has 0 shares": { + req: &vaulttypes.QueryMegavaultOwnerSharesRequest{ + Address: constants.AliceAccAddress.String(), + }, + ownerAddress: constants.AliceAccAddress.String(), + ownerShares: big.NewInt(0), + totalShares: big.NewInt(5_000), + megavaultEquity: big.NewInt(2_000_000), + }, + "Error: owner not found": { + req: &vaulttypes.QueryMegavaultOwnerSharesRequest{ + Address: constants.BobAccAddress.String(), + }, + ownerAddress: constants.AliceAccAddress.String(), + ownerShares: big.NewInt(100), + shareUnlocks: []vaulttypes.ShareUnlock{}, + totalShares: big.NewInt(5_000), + megavaultEquity: big.NewInt(2_000_000), + expectedErr: "owner not found", + }, + "Error: nil request": { + req: nil, + ownerAddress: constants.AliceAccAddress.String(), + ownerShares: big.NewInt(100), + shareUnlocks: []vaulttypes.ShareUnlock{}, + totalShares: big.NewInt(5_000), + megavaultEquity: big.NewInt(2_000_000), + expectedErr: "invalid request", + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + tApp := testapp.NewTestAppBuilder(t).WithGenesisDocFn(func() (genesis types.GenesisDoc) { + genesis = testapp.DefaultGenesis() + // Initialize megavault main vault with its equity. + testapp.UpdateGenesisDocWithAppStateForModule( + &genesis, + func(genesisState *satypes.GenesisState) { + genesisState.Subaccounts = []satypes.Subaccount{ + { + Id: &vaulttypes.MegavaultMainSubaccount, + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: constants.Usdc.Id, + Quantums: dtypes.NewIntFromBigInt(tc.megavaultEquity), + }, + }, + }, + } + }, + ) + return genesis + }).Build() + ctx := tApp.InitChain() + k := tApp.App.VaultKeeper + + err := k.SetTotalShares(ctx, vaulttypes.BigIntToNumShares(tc.totalShares)) + require.NoError(t, err) + err = k.SetOwnerShares( + ctx, + tc.ownerAddress, + vaulttypes.BigIntToNumShares(tc.ownerShares), + ) + require.NoError(t, err) + err = k.SetOwnerShareUnlocks( + ctx, + tc.ownerAddress, + vaulttypes.OwnerShareUnlocks{ + OwnerAddress: tc.ownerAddress, + ShareUnlocks: tc.shareUnlocks, + }, + ) + require.NoError(t, err) + + // Check OwnerShares query response is as expected. + res, err := k.MegavaultOwnerShares(ctx, tc.req) + if tc.expectedErr != "" { + require.ErrorContains(t, err, tc.expectedErr) + } else { + require.NoError(t, err) + require.Equal( + t, + vaulttypes.QueryMegavaultOwnerSharesResponse{ + Address: tc.req.Address, + Shares: vaulttypes.BigIntToNumShares(tc.ownerShares), + ShareUnlocks: tc.shareUnlocks, + Equity: dtypes.NewIntFromBigInt(tc.expectedOwnerEquity), + WithdrawableEquity: dtypes.NewIntFromBigInt(tc.expectedOwnerWithdrawableEquity), + }, + *res, + ) + } + }) + } +} diff --git a/protocol/x/vault/types/query.pb.go b/protocol/x/vault/types/query.pb.go index 3a20349960..040eb2c1f4 100644 --- a/protocol/x/vault/types/query.pb.go +++ b/protocol/x/vault/types/query.pb.go @@ -6,6 +6,7 @@ package types import ( context "context" fmt "fmt" + _ "github.com/cosmos/cosmos-proto" query "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" @@ -433,7 +434,7 @@ func (m *QueryMegavaultTotalSharesResponse) GetTotalShares() *NumShares { // QueryMegavaultOwnerSharesRequest is a request type for the // MegavaultOwnerShares RPC method. type QueryMegavaultOwnerSharesRequest struct { - Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` } func (m *QueryMegavaultOwnerSharesRequest) Reset() { *m = QueryMegavaultOwnerSharesRequest{} } @@ -469,18 +470,27 @@ func (m *QueryMegavaultOwnerSharesRequest) XXX_DiscardUnknown() { var xxx_messageInfo_QueryMegavaultOwnerSharesRequest proto.InternalMessageInfo -func (m *QueryMegavaultOwnerSharesRequest) GetPagination() *query.PageRequest { +func (m *QueryMegavaultOwnerSharesRequest) GetAddress() string { if m != nil { - return m.Pagination + return m.Address } - return nil + return "" } // QueryMegavaultOwnerSharesResponse is a response type for the // MegavaultOwnerShares RPC method. type QueryMegavaultOwnerSharesResponse struct { - OwnerShares []*OwnerShare `protobuf:"bytes,1,rep,name=owner_shares,json=ownerShares,proto3" json:"owner_shares,omitempty"` - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` + // Owner address. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Total number of shares that belong to the owner. + Shares NumShares `protobuf:"bytes,2,opt,name=shares,proto3" json:"shares"` + // All share unlocks. + ShareUnlocks []ShareUnlock `protobuf:"bytes,3,rep,name=share_unlocks,json=shareUnlocks,proto3" json:"share_unlocks"` + // Owner equity in megavault (in quote quantums). + Equity github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,4,opt,name=equity,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"equity"` + // Equity that owner can withdraw in quote quantums (as one cannot + // withdraw locked shares). + WithdrawableEquity github_com_dydxprotocol_v4_chain_protocol_dtypes.SerializableInt `protobuf:"bytes,5,opt,name=withdrawable_equity,json=withdrawableEquity,proto3,customtype=github.com/dydxprotocol/v4-chain/protocol/dtypes.SerializableInt" json:"withdrawable_equity"` } func (m *QueryMegavaultOwnerSharesResponse) Reset() { *m = QueryMegavaultOwnerSharesResponse{} } @@ -516,14 +526,121 @@ func (m *QueryMegavaultOwnerSharesResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryMegavaultOwnerSharesResponse proto.InternalMessageInfo -func (m *QueryMegavaultOwnerSharesResponse) GetOwnerShares() []*OwnerShare { +func (m *QueryMegavaultOwnerSharesResponse) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *QueryMegavaultOwnerSharesResponse) GetShares() NumShares { + if m != nil { + return m.Shares + } + return NumShares{} +} + +func (m *QueryMegavaultOwnerSharesResponse) GetShareUnlocks() []ShareUnlock { + if m != nil { + return m.ShareUnlocks + } + return nil +} + +// QueryMegavaultAllOwnerSharesRequest is a request type for the +// MegavaultAllOwnerShares RPC method. +type QueryMegavaultAllOwnerSharesRequest struct { + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryMegavaultAllOwnerSharesRequest) Reset() { *m = QueryMegavaultAllOwnerSharesRequest{} } +func (m *QueryMegavaultAllOwnerSharesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryMegavaultAllOwnerSharesRequest) ProtoMessage() {} +func (*QueryMegavaultAllOwnerSharesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_478fb8dc0ff21ea6, []int{10} +} +func (m *QueryMegavaultAllOwnerSharesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMegavaultAllOwnerSharesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMegavaultAllOwnerSharesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMegavaultAllOwnerSharesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMegavaultAllOwnerSharesRequest.Merge(m, src) +} +func (m *QueryMegavaultAllOwnerSharesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryMegavaultAllOwnerSharesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMegavaultAllOwnerSharesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMegavaultAllOwnerSharesRequest proto.InternalMessageInfo + +func (m *QueryMegavaultAllOwnerSharesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryMegavaultAllOwnerSharesResponse is a response type for the +// MegavaultAllOwnerShares RPC method. +type QueryMegavaultAllOwnerSharesResponse struct { + OwnerShares []*OwnerShare `protobuf:"bytes,1,rep,name=owner_shares,json=ownerShares,proto3" json:"owner_shares,omitempty"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryMegavaultAllOwnerSharesResponse) Reset() { *m = QueryMegavaultAllOwnerSharesResponse{} } +func (m *QueryMegavaultAllOwnerSharesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryMegavaultAllOwnerSharesResponse) ProtoMessage() {} +func (*QueryMegavaultAllOwnerSharesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_478fb8dc0ff21ea6, []int{11} +} +func (m *QueryMegavaultAllOwnerSharesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMegavaultAllOwnerSharesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMegavaultAllOwnerSharesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryMegavaultAllOwnerSharesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMegavaultAllOwnerSharesResponse.Merge(m, src) +} +func (m *QueryMegavaultAllOwnerSharesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryMegavaultAllOwnerSharesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMegavaultAllOwnerSharesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMegavaultAllOwnerSharesResponse proto.InternalMessageInfo + +func (m *QueryMegavaultAllOwnerSharesResponse) GetOwnerShares() []*OwnerShare { if m != nil { return m.OwnerShares } return nil } -func (m *QueryMegavaultOwnerSharesResponse) GetPagination() *query.PageResponse { +func (m *QueryMegavaultAllOwnerSharesResponse) GetPagination() *query.PageResponse { if m != nil { return m.Pagination } @@ -540,7 +657,7 @@ func (m *QueryVaultParamsRequest) Reset() { *m = QueryVaultParamsRequest func (m *QueryVaultParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryVaultParamsRequest) ProtoMessage() {} func (*QueryVaultParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_478fb8dc0ff21ea6, []int{10} + return fileDescriptor_478fb8dc0ff21ea6, []int{12} } func (m *QueryVaultParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -593,7 +710,7 @@ func (m *QueryVaultParamsResponse) Reset() { *m = QueryVaultParamsRespon func (m *QueryVaultParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryVaultParamsResponse) ProtoMessage() {} func (*QueryVaultParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_478fb8dc0ff21ea6, []int{11} + return fileDescriptor_478fb8dc0ff21ea6, []int{13} } func (m *QueryVaultParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -647,7 +764,7 @@ func (m *QueryMegavaultWithdrawalInfoRequest) Reset() { *m = QueryMegava func (m *QueryMegavaultWithdrawalInfoRequest) String() string { return proto.CompactTextString(m) } func (*QueryMegavaultWithdrawalInfoRequest) ProtoMessage() {} func (*QueryMegavaultWithdrawalInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_478fb8dc0ff21ea6, []int{12} + return fileDescriptor_478fb8dc0ff21ea6, []int{14} } func (m *QueryMegavaultWithdrawalInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -703,7 +820,7 @@ func (m *QueryMegavaultWithdrawalInfoResponse) Reset() { *m = QueryMegav func (m *QueryMegavaultWithdrawalInfoResponse) String() string { return proto.CompactTextString(m) } func (*QueryMegavaultWithdrawalInfoResponse) ProtoMessage() {} func (*QueryMegavaultWithdrawalInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_478fb8dc0ff21ea6, []int{13} + return fileDescriptor_478fb8dc0ff21ea6, []int{15} } func (m *QueryMegavaultWithdrawalInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -757,6 +874,8 @@ func init() { proto.RegisterType((*QueryMegavaultTotalSharesResponse)(nil), "dydxprotocol.vault.QueryMegavaultTotalSharesResponse") proto.RegisterType((*QueryMegavaultOwnerSharesRequest)(nil), "dydxprotocol.vault.QueryMegavaultOwnerSharesRequest") proto.RegisterType((*QueryMegavaultOwnerSharesResponse)(nil), "dydxprotocol.vault.QueryMegavaultOwnerSharesResponse") + proto.RegisterType((*QueryMegavaultAllOwnerSharesRequest)(nil), "dydxprotocol.vault.QueryMegavaultAllOwnerSharesRequest") + proto.RegisterType((*QueryMegavaultAllOwnerSharesResponse)(nil), "dydxprotocol.vault.QueryMegavaultAllOwnerSharesResponse") proto.RegisterType((*QueryVaultParamsRequest)(nil), "dydxprotocol.vault.QueryVaultParamsRequest") proto.RegisterType((*QueryVaultParamsResponse)(nil), "dydxprotocol.vault.QueryVaultParamsResponse") proto.RegisterType((*QueryMegavaultWithdrawalInfoRequest)(nil), "dydxprotocol.vault.QueryMegavaultWithdrawalInfoRequest") @@ -766,76 +885,86 @@ func init() { func init() { proto.RegisterFile("dydxprotocol/vault/query.proto", fileDescriptor_478fb8dc0ff21ea6) } var fileDescriptor_478fb8dc0ff21ea6 = []byte{ - // 1090 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xe6, 0x8f, 0x69, 0x9f, 0xdd, 0x3f, 0x0c, 0x69, 0x12, 0xdc, 0xe2, 0x34, 0x0b, 0xb4, - 0x24, 0x6d, 0x77, 0x95, 0xd0, 0xaa, 0x08, 0x21, 0xd4, 0x46, 0xa2, 0x34, 0x07, 0x68, 0xed, 0x44, - 0x20, 0x21, 0xc1, 0x32, 0xb6, 0x27, 0xce, 0x22, 0x7b, 0xc7, 0xde, 0x9d, 0x75, 0x62, 0xaa, 0x48, - 0x08, 0xc4, 0x81, 0x1b, 0x12, 0x57, 0x2e, 0xf0, 0x05, 0x38, 0x22, 0xce, 0x5c, 0x7a, 0xac, 0xc4, - 0x05, 0x71, 0xa8, 0x50, 0xc2, 0x37, 0xe0, 0x0b, 0xa0, 0x9d, 0x79, 0x5e, 0xef, 0xda, 0xbb, 0xce, - 0xb6, 0x32, 0x97, 0xc8, 0x99, 0x79, 0xef, 0xf7, 0x7e, 0xf3, 0xfe, 0xfc, 0xde, 0x42, 0xa9, 0xde, - 0xab, 0x1f, 0xb4, 0x5d, 0x2e, 0x78, 0x8d, 0x37, 0xcd, 0x2e, 0xf5, 0x9b, 0xc2, 0xec, 0xf8, 0xcc, - 0xed, 0x19, 0xf2, 0x90, 0x90, 0xe8, 0xbd, 0x21, 0xef, 0x8b, 0xf3, 0x0d, 0xde, 0xe0, 0xf2, 0xcc, - 0x0c, 0x7e, 0x29, 0xcb, 0xe2, 0xa5, 0x06, 0xe7, 0x8d, 0x26, 0x33, 0x69, 0xdb, 0x36, 0xa9, 0xe3, - 0x70, 0x41, 0x85, 0xcd, 0x1d, 0x0f, 0x6f, 0xd7, 0x6a, 0xdc, 0x6b, 0x71, 0xcf, 0xac, 0x52, 0x8f, - 0xa9, 0x00, 0x66, 0x77, 0xbd, 0xca, 0x04, 0x5d, 0x37, 0xdb, 0xb4, 0x61, 0x3b, 0xd2, 0x18, 0x6d, - 0x57, 0x63, 0x9c, 0x3c, 0xbf, 0x4a, 0x6b, 0x35, 0xee, 0x3b, 0xc2, 0x8b, 0xfc, 0x46, 0xd3, 0xe5, - 0x04, 0xfa, 0x6d, 0xea, 0xd2, 0x56, 0x3f, 0x6e, 0xd2, 0xfb, 0xbc, 0x3d, 0xea, 0xb2, 0x31, 0xf7, - 0xf2, 0xaf, 0xba, 0xd7, 0xe7, 0x81, 0x94, 0x03, 0xb6, 0x0f, 0x25, 0x68, 0x85, 0x75, 0x7c, 0xe6, - 0x09, 0xfd, 0x9b, 0x69, 0x78, 0x29, 0x76, 0xec, 0xb5, 0xb9, 0xe3, 0x31, 0xf2, 0x36, 0xe4, 0x54, - 0xf4, 0x25, 0xed, 0xb2, 0xf6, 0x46, 0x7e, 0xa3, 0x68, 0x8c, 0xa6, 0xcf, 0x50, 0x3e, 0x9b, 0xb9, - 0xc7, 0x4f, 0x97, 0xa7, 0x96, 0xb4, 0x0a, 0x7a, 0x90, 0x4f, 0x61, 0xa1, 0xce, 0x76, 0x03, 0x0b, - 0xab, 0xe3, 0x73, 0x61, 0x3b, 0x0d, 0x0b, 0xb1, 0xa6, 0x25, 0xd6, 0x4a, 0x12, 0x56, 0x59, 0x59, - 0x22, 0xe4, 0x6c, 0x00, 0x59, 0x99, 0x47, 0x98, 0xd8, 0x1d, 0x29, 0xc3, 0x39, 0xde, 0x66, 0x2e, - 0x15, 0xdc, 0xed, 0xe3, 0xce, 0x48, 0x5c, 0x3d, 0x09, 0xf7, 0x01, 0x9a, 0xc6, 0x80, 0xcf, 0xf2, - 0xd8, 0xa9, 0xfe, 0x19, 0xbc, 0x28, 0x93, 0xf0, 0x51, 0xe0, 0x82, 0xa9, 0x21, 0xeb, 0x30, 0x2b, - 0x7a, 0x6d, 0x26, 0x13, 0x70, 0x76, 0xe3, 0x95, 0x24, 0x70, 0x69, 0xbf, 0xd3, 0x6b, 0xb3, 0x8a, - 0x34, 0x25, 0x0b, 0x90, 0x73, 0xfc, 0x56, 0x95, 0xb9, 0xf2, 0xa5, 0x67, 0x2a, 0xf8, 0x9f, 0xfe, - 0xdb, 0x0c, 0x26, 0x1f, 0x03, 0x60, 0x92, 0xdf, 0x81, 0x53, 0x12, 0xc7, 0xb2, 0xeb, 0x98, 0xe6, - 0x8b, 0xa9, 0x51, 0xb6, 0xea, 0xc8, 0xfd, 0x85, 0xae, 0xfa, 0x97, 0x94, 0xe1, 0xcc, 0xa0, 0x8b, - 0x02, 0x08, 0x95, 0xdd, 0x2b, 0x71, 0x88, 0x48, 0xd3, 0x19, 0xdb, 0xe1, 0xef, 0x10, 0xad, 0xe0, - 0x45, 0xce, 0xc8, 0xe7, 0x90, 0x63, 0x1d, 0xdf, 0x16, 0x3d, 0x99, 0xd1, 0xc2, 0xe6, 0xfd, 0xc0, - 0xe6, 0xaf, 0xa7, 0xcb, 0x77, 0x1a, 0xb6, 0xd8, 0xf3, 0xab, 0x46, 0x8d, 0xb7, 0xcc, 0x78, 0x9b, - 0xdd, 0xbc, 0x51, 0xdb, 0xa3, 0xb6, 0x63, 0x86, 0x27, 0xf5, 0x20, 0x11, 0x9e, 0xb1, 0xcd, 0x5c, - 0x9b, 0x36, 0xed, 0x2f, 0x69, 0xb5, 0xc9, 0xb6, 0x1c, 0x51, 0x41, 0x5c, 0xb2, 0x0b, 0xa7, 0x6d, - 0xa7, 0xcb, 0x1c, 0xc1, 0xdd, 0xde, 0xd2, 0xec, 0x84, 0x83, 0x0c, 0xa0, 0xc9, 0x7d, 0x28, 0xa8, - 0xd4, 0x62, 0x87, 0xcc, 0xc9, 0xdc, 0x2c, 0xa7, 0xa6, 0x37, 0xd6, 0x1e, 0xf9, 0xee, 0xe0, 0x48, - 0xb7, 0xe0, 0x82, 0x2c, 0xdd, 0xdd, 0x66, 0x53, 0x5a, 0xf6, 0x47, 0x87, 0xdc, 0x03, 0x18, 0x0c, - 0x3c, 0xd6, 0xef, 0x8a, 0xa1, 0xd4, 0xc1, 0x08, 0xd4, 0xc1, 0x50, 0xf2, 0x83, 0xea, 0x60, 0x3c, - 0xa4, 0x0d, 0x86, 0xbe, 0x95, 0x88, 0xa7, 0xfe, 0x93, 0x06, 0x0b, 0xc3, 0x11, 0xb0, 0x41, 0xde, - 0x85, 0x9c, 0xa4, 0x12, 0x4c, 0xe1, 0xcc, 0x68, 0x6d, 0xfb, 0x93, 0x33, 0xdc, 0x58, 0x15, 0xf4, - 0x22, 0xef, 0xc7, 0x28, 0xaa, 0xfe, 0xb8, 0x7a, 0x22, 0x45, 0x04, 0x89, 0x72, 0xd4, 0xe1, 0xb2, - 0x0c, 0xf3, 0x01, 0x6b, 0x50, 0x89, 0xbd, 0xc3, 0x05, 0x6d, 0x6e, 0x07, 0xf2, 0x13, 0x4a, 0x09, - 0x83, 0x95, 0x31, 0x36, 0xf8, 0xa2, 0x3b, 0x50, 0x10, 0xc1, 0xb1, 0x25, 0xa5, 0xab, 0xaf, 0x2e, - 0x89, 0xc3, 0xf5, 0xa1, 0xdf, 0x42, 0xe7, 0xbc, 0x18, 0x20, 0xe9, 0x5f, 0x0c, 0x53, 0x79, 0xb0, - 0xef, 0x30, 0x37, 0x46, 0x65, 0xa8, 0x34, 0x33, 0xcf, 0x5d, 0x9a, 0x5f, 0xb4, 0xe1, 0x37, 0xc5, - 0x82, 0xe1, 0x9b, 0xee, 0x42, 0x81, 0x07, 0xc7, 0x83, 0x37, 0x05, 0xb5, 0x2a, 0x25, 0xaa, 0x51, - 0xe8, 0x5e, 0xc9, 0xf3, 0x01, 0xd4, 0xe4, 0x0a, 0x55, 0x87, 0xc5, 0x41, 0x3f, 0xc4, 0xa4, 0x7e, - 0x92, 0x7a, 0xf6, 0xb3, 0x06, 0x4b, 0xa3, 0x61, 0x26, 0xa2, 0x6a, 0xc3, 0x83, 0x3b, 0xfd, 0xdc, - 0x83, 0x7b, 0x00, 0xaf, 0xc6, 0x6b, 0xf7, 0xb1, 0x2d, 0xf6, 0xea, 0x2e, 0xdd, 0xa7, 0xcd, 0x2d, - 0x67, 0x97, 0xf7, 0xd3, 0x52, 0x06, 0xa2, 0xea, 0x66, 0x09, 0x6e, 0xed, 0xa3, 0x49, 0xa6, 0xbe, - 0xc4, 0xa0, 0xe7, 0x95, 0xfb, 0x0e, 0xef, 0xe3, 0x07, 0x72, 0xff, 0xda, 0xf8, 0xd0, 0x98, 0xaa, - 0xc9, 0xc7, 0x26, 0x5f, 0x69, 0xb0, 0xc8, 0x0e, 0xda, 0xac, 0x26, 0x58, 0x5d, 0xae, 0x5f, 0x66, - 0x75, 0x7c, 0xea, 0x08, 0x1f, 0x73, 0x39, 0x49, 0xbd, 0xbd, 0xd0, 0x0f, 0x14, 0x2c, 0x68, 0x56, - 0xc6, 0x30, 0xc4, 0x83, 0xf3, 0xad, 0xfe, 0xc3, 0xad, 0xff, 0x69, 0x9f, 0x9c, 0x0b, 0x23, 0xbc, - 0xa7, 0x16, 0xcb, 0xbd, 0x21, 0x61, 0x99, 0xcd, 0x9e, 0xc4, 0xa8, 0xbc, 0x6c, 0xfc, 0x7b, 0x0a, - 0xe6, 0x64, 0xed, 0xc8, 0x21, 0xe4, 0xf0, 0x8b, 0x23, 0x5d, 0x76, 0x63, 0x13, 0x56, 0xbc, 0x7a, - 0xa2, 0x9d, 0xaa, 0xbb, 0xae, 0x7f, 0xfd, 0xc7, 0x3f, 0x3f, 0x4c, 0x5f, 0x22, 0x45, 0x33, 0xf5, - 0xab, 0x8f, 0x7c, 0xa7, 0xc1, 0x9c, 0xec, 0x70, 0xf2, 0xfa, 0x49, 0xaa, 0xaf, 0xa2, 0x67, 0x5c, - 0x0e, 0xfa, 0xba, 0x0c, 0x7e, 0x8d, 0xac, 0x9a, 0x69, 0x5f, 0x8c, 0xe6, 0xa3, 0x20, 0xe9, 0x87, - 0xe6, 0x23, 0x35, 0xee, 0x87, 0xe4, 0x5b, 0x0d, 0x4e, 0x87, 0xdb, 0x89, 0xac, 0xa6, 0x06, 0x1a, - 0xde, 0x91, 0xc5, 0xb5, 0x2c, 0xa6, 0xc8, 0x6b, 0x45, 0xf2, 0xba, 0x48, 0x5e, 0x4e, 0xe5, 0x45, - 0x7e, 0xd5, 0x60, 0x3e, 0x69, 0xbd, 0x90, 0x9b, 0xa9, 0x71, 0xc6, 0x6c, 0xac, 0xe2, 0xad, 0x67, - 0xf4, 0x42, 0xa2, 0x1b, 0x92, 0xe8, 0x75, 0xb2, 0x96, 0x44, 0x34, 0xec, 0x4b, 0x33, 0xda, 0x8e, - 0x71, 0xe6, 0x91, 0x25, 0x92, 0x85, 0xf9, 0xe8, 0x82, 0xcb, 0xc2, 0x3c, 0x61, 0x53, 0x65, 0x65, - 0x1e, 0xdd, 0x66, 0xe4, 0x47, 0x0d, 0xf2, 0x11, 0xa5, 0x25, 0xd7, 0xc6, 0xb7, 0x59, 0x7c, 0x22, - 0xae, 0x67, 0x33, 0xce, 0x42, 0x4f, 0x8d, 0xc5, 0x48, 0x6b, 0xfe, 0xae, 0xc1, 0x62, 0x8a, 0xcc, - 0x92, 0xdb, 0x27, 0x67, 0x29, 0x71, 0x27, 0x14, 0xdf, 0x7a, 0x76, 0x47, 0x7c, 0xc2, 0x2d, 0xf9, - 0x04, 0x93, 0xdc, 0x18, 0x9f, 0xe1, 0xfd, 0xd0, 0xdb, 0xb2, 0x9d, 0x5d, 0xbe, 0x59, 0x7e, 0x7c, - 0x54, 0xd2, 0x9e, 0x1c, 0x95, 0xb4, 0xbf, 0x8f, 0x4a, 0xda, 0xf7, 0xc7, 0xa5, 0xa9, 0x27, 0xc7, - 0xa5, 0xa9, 0x3f, 0x8f, 0x4b, 0x53, 0x9f, 0xdc, 0xce, 0x2e, 0x95, 0x07, 0x18, 0x46, 0x2a, 0x66, - 0x35, 0x27, 0xcf, 0xdf, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x82, 0xa3, 0x58, 0x95, 0x18, 0x0f, - 0x00, 0x00, + // 1258 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcf, 0x6f, 0x1b, 0xc5, + 0x17, 0xcf, 0xe6, 0x87, 0xfb, 0xcd, 0x4b, 0xd2, 0xf6, 0x3b, 0x4d, 0x93, 0xd4, 0x2d, 0x4e, 0xb3, + 0x94, 0x96, 0xa4, 0x8d, 0x97, 0x84, 0xb4, 0x45, 0x50, 0xa1, 0x26, 0x12, 0xa5, 0x41, 0x82, 0xd6, + 0x4e, 0x28, 0x12, 0x12, 0x2c, 0x63, 0x7b, 0xe2, 0xac, 0x58, 0xef, 0x38, 0xbb, 0xb3, 0x49, 0x4c, + 0x14, 0x09, 0x81, 0x38, 0x70, 0x43, 0xe2, 0xca, 0x05, 0xfe, 0x04, 0x84, 0x84, 0x38, 0x70, 0x40, + 0xf4, 0xd0, 0x63, 0x05, 0x17, 0xc4, 0xa1, 0x42, 0x09, 0x7f, 0x08, 0xda, 0x99, 0xb7, 0xf6, 0xae, + 0xb3, 0x76, 0xb6, 0x95, 0x7b, 0x89, 0xbc, 0x33, 0xef, 0x7d, 0x3e, 0xef, 0xbd, 0x79, 0xbf, 0x02, + 0xb9, 0x4a, 0xa3, 0xb2, 0x5b, 0x77, 0xb9, 0xe0, 0x65, 0x6e, 0x1b, 0xdb, 0xd4, 0xb7, 0x85, 0xb1, + 0xe5, 0x33, 0xb7, 0x91, 0x97, 0x87, 0x84, 0x44, 0xef, 0xf3, 0xf2, 0x3e, 0x7b, 0xae, 0xcc, 0xbd, + 0x1a, 0xf7, 0x4c, 0x79, 0x6c, 0xa8, 0x0f, 0x25, 0x9e, 0x9d, 0x53, 0x5f, 0x46, 0x89, 0x7a, 0x4c, + 0xe1, 0x18, 0xdb, 0x0b, 0x25, 0x26, 0xe8, 0x82, 0x51, 0xa7, 0x55, 0xcb, 0xa1, 0xc2, 0xe2, 0x0e, + 0xca, 0x8e, 0x57, 0x79, 0x95, 0x2b, 0x8c, 0xe0, 0x17, 0x9e, 0x5e, 0xa8, 0x72, 0x5e, 0xb5, 0x99, + 0x41, 0xeb, 0x96, 0x41, 0x1d, 0x87, 0x0b, 0xa9, 0x12, 0xe2, 0xcf, 0xc6, 0xcc, 0xf5, 0xfc, 0x12, + 0x2d, 0x97, 0xb9, 0xef, 0x08, 0x2f, 0xf2, 0x1b, 0x45, 0xa7, 0x13, 0x3c, 0xab, 0x53, 0x97, 0xd6, + 0x42, 0xac, 0x24, 0xd7, 0xbd, 0x4d, 0xea, 0xb2, 0x2e, 0xf7, 0xf2, 0xaf, 0xba, 0xd7, 0xc7, 0x81, + 0x14, 0x02, 0x0f, 0xef, 0x4b, 0xd0, 0x22, 0xdb, 0xf2, 0x99, 0x27, 0xf4, 0x2f, 0xfb, 0xe1, 0x4c, + 0xec, 0xd8, 0xab, 0x73, 0xc7, 0x63, 0xe4, 0x75, 0xc8, 0x28, 0xf6, 0x29, 0xed, 0xa2, 0xf6, 0xf2, + 0xc8, 0x62, 0x36, 0x7f, 0x34, 0xb2, 0x79, 0xa5, 0xb3, 0x92, 0x79, 0xf4, 0x64, 0xba, 0x6f, 0x4a, + 0x2b, 0xa2, 0x06, 0xf9, 0x08, 0x26, 0x2a, 0x6c, 0x23, 0x90, 0x30, 0xb7, 0x7c, 0x2e, 0x2c, 0xa7, + 0x6a, 0x22, 0x56, 0xbf, 0xc4, 0x9a, 0x49, 0xc2, 0x2a, 0x28, 0x49, 0x84, 0x1c, 0x0c, 0x20, 0x8b, + 0xe3, 0x08, 0x13, 0xbb, 0x23, 0x05, 0x38, 0xc5, 0xeb, 0xcc, 0xa5, 0x82, 0xbb, 0x21, 0xee, 0x80, + 0xc4, 0xd5, 0x93, 0x70, 0xef, 0xa1, 0x68, 0x0c, 0xf8, 0x24, 0x8f, 0x9d, 0xea, 0x1f, 0xc3, 0xff, + 0x65, 0x10, 0x1e, 0x04, 0x2a, 0x18, 0x1a, 0xb2, 0x00, 0x83, 0xa2, 0x51, 0x67, 0x32, 0x00, 0x27, + 0x17, 0x5f, 0x48, 0x02, 0x97, 0xf2, 0xeb, 0x8d, 0x3a, 0x2b, 0x4a, 0x51, 0x32, 0x01, 0x19, 0xc7, + 0xaf, 0x95, 0x98, 0x2b, 0x3d, 0x1d, 0x2b, 0xe2, 0x97, 0xfe, 0xcb, 0x00, 0x06, 0x1f, 0x09, 0x30, + 0xc8, 0xb7, 0xe0, 0x7f, 0x12, 0xc7, 0xb4, 0x2a, 0x18, 0xe6, 0xf3, 0x1d, 0x59, 0x56, 0x2b, 0x68, + 0xfb, 0x89, 0x6d, 0xf5, 0x49, 0x0a, 0x30, 0xd6, 0xca, 0xa2, 0x00, 0x42, 0x45, 0xf7, 0x72, 0x1c, + 0x22, 0x92, 0x74, 0xf9, 0xb5, 0xe6, 0xef, 0x26, 0xda, 0xa8, 0x17, 0x39, 0x23, 0x9f, 0x40, 0x86, + 0x6d, 0xf9, 0x96, 0x68, 0xc8, 0x88, 0x8e, 0xae, 0xdc, 0x0d, 0x64, 0xfe, 0x7e, 0x32, 0x7d, 0xbb, + 0x6a, 0x89, 0x4d, 0xbf, 0x94, 0x2f, 0xf3, 0x9a, 0x11, 0x4f, 0xb3, 0xa5, 0xf9, 0xf2, 0x26, 0xb5, + 0x1c, 0xa3, 0x79, 0x52, 0x09, 0x02, 0xe1, 0xe5, 0xd7, 0x98, 0x6b, 0x51, 0xdb, 0xfa, 0x8c, 0x96, + 0x6c, 0xb6, 0xea, 0x88, 0x22, 0xe2, 0x92, 0x0d, 0x18, 0xb6, 0x9c, 0x6d, 0xe6, 0x08, 0xee, 0x36, + 0xa6, 0x06, 0x7b, 0x4c, 0xd2, 0x82, 0x26, 0x77, 0x61, 0x54, 0x85, 0x16, 0x33, 0x64, 0x48, 0xc6, + 0x66, 0xba, 0x63, 0x78, 0x63, 0xe9, 0x31, 0xb2, 0xdd, 0x3a, 0xd2, 0x4d, 0x38, 0x2b, 0x9f, 0x6e, + 0xd9, 0xb6, 0xa5, 0x64, 0x58, 0x3a, 0xe4, 0x0e, 0x40, 0xab, 0x49, 0xe0, 0xfb, 0x5d, 0xce, 0x63, + 0x7f, 0x09, 0x3a, 0x4a, 0x5e, 0x75, 0x26, 0xec, 0x28, 0xf9, 0xfb, 0xb4, 0xca, 0x50, 0xb7, 0x18, + 0xd1, 0xd4, 0xbf, 0xd7, 0x60, 0xa2, 0x9d, 0x01, 0x13, 0xe4, 0x4d, 0xc8, 0x48, 0x53, 0x82, 0x2a, + 0x1c, 0x38, 0xfa, 0xb6, 0x61, 0xe5, 0xb4, 0x27, 0x56, 0x11, 0xb5, 0xc8, 0xdb, 0x31, 0x13, 0x55, + 0x7e, 0x5c, 0x39, 0xd6, 0x44, 0x04, 0x89, 0xda, 0xa8, 0xc3, 0x45, 0x49, 0xf3, 0x2e, 0xab, 0x52, + 0x89, 0xbd, 0xce, 0x05, 0xb5, 0xd7, 0x82, 0xf6, 0xd3, 0x6c, 0x25, 0x0c, 0x66, 0xba, 0xc8, 0xa0, + 0x47, 0xb7, 0x61, 0x54, 0x04, 0xc7, 0xa6, 0x6c, 0x5d, 0x61, 0x77, 0x49, 0x2c, 0xae, 0xf7, 0xfc, + 0x1a, 0x2a, 0x8f, 0x88, 0x16, 0x92, 0xfe, 0xa0, 0xdd, 0x94, 0x7b, 0x3b, 0x0e, 0x73, 0x63, 0xa6, + 0x90, 0x45, 0x38, 0x41, 0x2b, 0x15, 0x97, 0x79, 0x8a, 0x60, 0x78, 0x65, 0xea, 0x8f, 0x9f, 0xe6, + 0xc7, 0xd1, 0xef, 0x65, 0x75, 0xb3, 0x26, 0x5c, 0xcb, 0xa9, 0x16, 0x43, 0x41, 0xfd, 0xd7, 0x81, + 0x76, 0xfb, 0x63, 0xc0, 0x68, 0xff, 0x33, 0x20, 0x93, 0x37, 0x20, 0x83, 0xde, 0xf6, 0xa7, 0xf0, + 0x16, 0x73, 0x10, 0x55, 0xc8, 0x3b, 0x30, 0x26, 0x7f, 0x99, 0xbe, 0x63, 0xf3, 0xf2, 0xa7, 0x41, + 0xaf, 0x1b, 0xe8, 0x94, 0xc9, 0x12, 0xe0, 0x7d, 0x29, 0xd7, 0x2c, 0xef, 0xd6, 0x91, 0x17, 0x29, + 0xef, 0xc1, 0xe7, 0x54, 0xde, 0x0d, 0x38, 0xb3, 0x63, 0x89, 0xcd, 0x8a, 0x4b, 0x77, 0x82, 0x2b, + 0x13, 0xe9, 0x86, 0x7a, 0x4c, 0x47, 0xa2, 0x24, 0x6f, 0x49, 0x0e, 0xbd, 0x06, 0x2f, 0xc6, 0x9f, + 0x6f, 0xd9, 0xb6, 0x13, 0x52, 0xa3, 0x57, 0x55, 0xfb, 0xa3, 0x06, 0x97, 0xba, 0xf3, 0x61, 0xc6, + 0x2c, 0xc3, 0x28, 0x0f, 0x8e, 0x5b, 0x19, 0x1f, 0xbc, 0x5f, 0x2e, 0x71, 0x56, 0x35, 0xd5, 0x8b, + 0x23, 0xbc, 0x05, 0xd5, 0xbb, 0x32, 0xae, 0xc0, 0x64, 0xab, 0x5b, 0xc4, 0x16, 0x81, 0x5e, 0x4e, + 0xbb, 0x1f, 0x34, 0x98, 0x3a, 0x4a, 0xd3, 0x93, 0x99, 0xd7, 0xde, 0xd6, 0xfb, 0x9f, 0xb9, 0xad, + 0xef, 0xb6, 0xa7, 0xcb, 0x07, 0x61, 0x4a, 0xd9, 0xab, 0xce, 0x06, 0x0f, 0xc3, 0x52, 0x00, 0xa2, + 0xde, 0xcd, 0x14, 0xdc, 0x0c, 0xb3, 0x2e, 0x55, 0xd7, 0x42, 0xd2, 0xd3, 0x4a, 0x7d, 0x9d, 0x87, + 0xf8, 0xc1, 0x32, 0x70, 0xa9, 0x3b, 0x35, 0x86, 0xaa, 0xf7, 0xdc, 0xe4, 0x73, 0x0d, 0x26, 0xd9, + 0x6e, 0x9d, 0x95, 0x05, 0xab, 0xc8, 0xe5, 0x8c, 0x99, 0x5b, 0x3e, 0x75, 0x84, 0x8f, 0xb1, 0xec, + 0x65, 0x91, 0x9e, 0x0d, 0x89, 0x82, 0xf5, 0x8d, 0x15, 0x90, 0x86, 0x78, 0x70, 0xba, 0x16, 0x3a, + 0x6e, 0x3e, 0xa7, 0x6d, 0xe3, 0x54, 0x93, 0x41, 0x35, 0x07, 0x72, 0xa7, 0x6d, 0xec, 0x0c, 0xa6, + 0x0f, 0x62, 0x74, 0xf8, 0x2c, 0x3e, 0x04, 0x18, 0x92, 0x6f, 0x47, 0xf6, 0x21, 0x83, 0xfb, 0x68, + 0xe7, 0xa1, 0x1c, 0xab, 0xb0, 0xec, 0x95, 0x63, 0xe5, 0xd4, 0xbb, 0xeb, 0xfa, 0x17, 0x7f, 0xfe, + 0xfb, 0x6d, 0xff, 0x05, 0x92, 0x35, 0x3a, 0xfe, 0x4f, 0x40, 0xbe, 0xd6, 0x60, 0x48, 0x66, 0x38, + 0x79, 0xe9, 0xb8, 0x9d, 0x40, 0xb1, 0xa7, 0x5c, 0x1d, 0xf4, 0x05, 0x49, 0x7e, 0x95, 0xcc, 0x1a, + 0x9d, 0xfe, 0x9f, 0x30, 0xf6, 0x82, 0xa0, 0xef, 0x1b, 0x7b, 0xaa, 0xdc, 0xf7, 0xc9, 0x57, 0x1a, + 0x0c, 0x37, 0x77, 0x17, 0x32, 0xdb, 0x91, 0xa8, 0x7d, 0x83, 0xca, 0xce, 0xa5, 0x11, 0x45, 0xbb, + 0x66, 0xa4, 0x5d, 0xe7, 0xc9, 0xb9, 0x8e, 0x76, 0x91, 0x9f, 0x35, 0x18, 0x4f, 0x5a, 0x3e, 0xc8, + 0x52, 0x47, 0x9e, 0x2e, 0xfb, 0x4c, 0xf6, 0xfa, 0x53, 0x6a, 0xa1, 0xa1, 0x8b, 0xd2, 0xd0, 0x6b, + 0x64, 0x2e, 0xc9, 0xd0, 0x66, 0x5e, 0x1a, 0xd1, 0x74, 0x24, 0xbf, 0x45, 0x2d, 0x8f, 0x0c, 0x91, + 0x34, 0x96, 0x1f, 0x9d, 0x71, 0x69, 0x2c, 0x4f, 0x98, 0x54, 0xfa, 0x2d, 0x69, 0xf9, 0x0d, 0xb2, + 0xd4, 0xdd, 0xf2, 0xe8, 0x34, 0x33, 0xf6, 0x70, 0xc9, 0xd9, 0x27, 0x0f, 0x35, 0x98, 0xec, 0x30, + 0x0b, 0xc9, 0xcd, 0xe3, 0x0d, 0x4a, 0x9c, 0xd6, 0xd9, 0xd7, 0x9e, 0x5e, 0x11, 0x9d, 0xb9, 0x21, + 0x9d, 0x79, 0x85, 0xe4, 0xbb, 0x3b, 0x43, 0x6d, 0xdb, 0x8c, 0x3a, 0x44, 0xbe, 0xd3, 0x60, 0x24, + 0x32, 0x3a, 0xc8, 0xd5, 0xee, 0x75, 0x13, 0x2f, 0xf1, 0x6b, 0xe9, 0x84, 0xd3, 0x64, 0x8a, 0xaa, + 0xf3, 0x23, 0xb5, 0xf6, 0x7b, 0x34, 0xca, 0xf1, 0xb9, 0x91, 0x26, 0xca, 0x89, 0x43, 0x2e, 0x4d, + 0x94, 0x93, 0x47, 0x94, 0x7e, 0x5d, 0xba, 0x60, 0x90, 0xf9, 0xee, 0x51, 0x6e, 0xae, 0x6b, 0xb6, + 0x69, 0x39, 0x1b, 0x7c, 0xa5, 0xf0, 0xe8, 0x20, 0xa7, 0x3d, 0x3e, 0xc8, 0x69, 0xff, 0x1c, 0xe4, + 0xb4, 0x6f, 0x0e, 0x73, 0x7d, 0x8f, 0x0f, 0x73, 0x7d, 0x7f, 0x1d, 0xe6, 0xfa, 0x3e, 0xbc, 0x99, + 0xbe, 0xf7, 0xef, 0x22, 0x8d, 0x1c, 0x01, 0xa5, 0x8c, 0x3c, 0x7f, 0xf5, 0xbf, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x27, 0xfa, 0xf8, 0xdb, 0x22, 0x12, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -860,6 +989,8 @@ type QueryClient interface { MegavaultTotalShares(ctx context.Context, in *QueryMegavaultTotalSharesRequest, opts ...grpc.CallOption) (*QueryMegavaultTotalSharesResponse, error) // Queries owner shares of megavault. MegavaultOwnerShares(ctx context.Context, in *QueryMegavaultOwnerSharesRequest, opts ...grpc.CallOption) (*QueryMegavaultOwnerSharesResponse, error) + // Queries all owner shares of megavault. + MegavaultAllOwnerShares(ctx context.Context, in *QueryMegavaultAllOwnerSharesRequest, opts ...grpc.CallOption) (*QueryMegavaultAllOwnerSharesResponse, error) // Queries vault params of a vault. VaultParams(ctx context.Context, in *QueryVaultParamsRequest, opts ...grpc.CallOption) (*QueryVaultParamsResponse, error) // Queries withdrawal info for megavault. @@ -919,6 +1050,15 @@ func (c *queryClient) MegavaultOwnerShares(ctx context.Context, in *QueryMegavau return out, nil } +func (c *queryClient) MegavaultAllOwnerShares(ctx context.Context, in *QueryMegavaultAllOwnerSharesRequest, opts ...grpc.CallOption) (*QueryMegavaultAllOwnerSharesResponse, error) { + out := new(QueryMegavaultAllOwnerSharesResponse) + err := c.cc.Invoke(ctx, "/dydxprotocol.vault.Query/MegavaultAllOwnerShares", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) VaultParams(ctx context.Context, in *QueryVaultParamsRequest, opts ...grpc.CallOption) (*QueryVaultParamsResponse, error) { out := new(QueryVaultParamsResponse) err := c.cc.Invoke(ctx, "/dydxprotocol.vault.Query/VaultParams", in, out, opts...) @@ -949,6 +1089,8 @@ type QueryServer interface { MegavaultTotalShares(context.Context, *QueryMegavaultTotalSharesRequest) (*QueryMegavaultTotalSharesResponse, error) // Queries owner shares of megavault. MegavaultOwnerShares(context.Context, *QueryMegavaultOwnerSharesRequest) (*QueryMegavaultOwnerSharesResponse, error) + // Queries all owner shares of megavault. + MegavaultAllOwnerShares(context.Context, *QueryMegavaultAllOwnerSharesRequest) (*QueryMegavaultAllOwnerSharesResponse, error) // Queries vault params of a vault. VaultParams(context.Context, *QueryVaultParamsRequest) (*QueryVaultParamsResponse, error) // Queries withdrawal info for megavault. @@ -974,6 +1116,9 @@ func (*UnimplementedQueryServer) MegavaultTotalShares(ctx context.Context, req * func (*UnimplementedQueryServer) MegavaultOwnerShares(ctx context.Context, req *QueryMegavaultOwnerSharesRequest) (*QueryMegavaultOwnerSharesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method MegavaultOwnerShares not implemented") } +func (*UnimplementedQueryServer) MegavaultAllOwnerShares(ctx context.Context, req *QueryMegavaultAllOwnerSharesRequest) (*QueryMegavaultAllOwnerSharesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MegavaultAllOwnerShares not implemented") +} func (*UnimplementedQueryServer) VaultParams(ctx context.Context, req *QueryVaultParamsRequest) (*QueryVaultParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VaultParams not implemented") } @@ -1075,6 +1220,24 @@ func _Query_MegavaultOwnerShares_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _Query_MegavaultAllOwnerShares_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryMegavaultAllOwnerSharesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).MegavaultAllOwnerShares(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dydxprotocol.vault.Query/MegavaultAllOwnerShares", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).MegavaultAllOwnerShares(ctx, req.(*QueryMegavaultAllOwnerSharesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_VaultParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryVaultParamsRequest) if err := dec(in); err != nil { @@ -1135,6 +1298,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "MegavaultOwnerShares", Handler: _Query_MegavaultOwnerShares_Handler, }, + { + MethodName: "MegavaultAllOwnerShares", + Handler: _Query_MegavaultAllOwnerShares_Handler, + }, { MethodName: "VaultParams", Handler: _Query_VaultParams_Handler, @@ -1488,6 +1655,110 @@ func (m *QueryMegavaultOwnerSharesRequest) MarshalTo(dAtA []byte) (int, error) { } func (m *QueryMegavaultOwnerSharesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryMegavaultOwnerSharesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMegavaultOwnerSharesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMegavaultOwnerSharesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.WithdrawableEquity.Size() + i -= size + if _, err := m.WithdrawableEquity.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.Equity.Size() + i -= size + if _, err := m.Equity.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.ShareUnlocks) > 0 { + for iNdEx := len(m.ShareUnlocks) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ShareUnlocks[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.Shares.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryMegavaultAllOwnerSharesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryMegavaultAllOwnerSharesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMegavaultAllOwnerSharesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1502,12 +1773,12 @@ func (m *QueryMegavaultOwnerSharesRequest) MarshalToSizedBuffer(dAtA []byte) (in i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *QueryMegavaultOwnerSharesResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryMegavaultAllOwnerSharesResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1517,12 +1788,12 @@ func (m *QueryMegavaultOwnerSharesResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryMegavaultOwnerSharesResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryMegavaultAllOwnerSharesResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryMegavaultOwnerSharesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryMegavaultAllOwnerSharesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1852,6 +2123,44 @@ func (m *QueryMegavaultTotalSharesResponse) Size() (n int) { } func (m *QueryMegavaultOwnerSharesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryMegavaultOwnerSharesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = m.Shares.Size() + n += 1 + l + sovQuery(uint64(l)) + if len(m.ShareUnlocks) > 0 { + for _, e := range m.ShareUnlocks { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = m.Equity.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.WithdrawableEquity.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryMegavaultAllOwnerSharesRequest) Size() (n int) { if m == nil { return 0 } @@ -1864,7 +2173,7 @@ func (m *QueryMegavaultOwnerSharesRequest) Size() (n int) { return n } -func (m *QueryMegavaultOwnerSharesResponse) Size() (n int) { +func (m *QueryMegavaultAllOwnerSharesResponse) Size() (n int) { if m == nil { return 0 } @@ -2818,7 +3127,304 @@ func (m *QueryMegavaultOwnerSharesRequest) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryMegavaultOwnerSharesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryMegavaultOwnerSharesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMegavaultOwnerSharesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMegavaultOwnerSharesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Shares.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ShareUnlocks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ShareUnlocks = append(m.ShareUnlocks, ShareUnlock{}) + if err := m.ShareUnlocks[len(m.ShareUnlocks)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Equity", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Equity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WithdrawableEquity", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.WithdrawableEquity.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryMegavaultAllOwnerSharesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryMegavaultAllOwnerSharesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMegavaultAllOwnerSharesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } @@ -2875,7 +3481,7 @@ func (m *QueryMegavaultOwnerSharesRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryMegavaultOwnerSharesResponse) Unmarshal(dAtA []byte) error { +func (m *QueryMegavaultAllOwnerSharesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2898,10 +3504,10 @@ func (m *QueryMegavaultOwnerSharesResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryMegavaultOwnerSharesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryMegavaultAllOwnerSharesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryMegavaultOwnerSharesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryMegavaultAllOwnerSharesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: diff --git a/protocol/x/vault/types/query.pb.gw.go b/protocol/x/vault/types/query.pb.gw.go index 87c4c5c0a8..dc98d0799f 100644 --- a/protocol/x/vault/types/query.pb.gw.go +++ b/protocol/x/vault/types/query.pb.gw.go @@ -187,38 +187,92 @@ func local_request_Query_MegavaultTotalShares_0(ctx context.Context, marshaler r } +func request_Query_MegavaultOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultOwnerSharesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := client.MegavaultOwnerShares(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_MegavaultOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultOwnerSharesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.MegavaultOwnerShares(ctx, &protoReq) + return msg, metadata, err + +} + var ( - filter_Query_MegavaultOwnerShares_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + filter_Query_MegavaultAllOwnerShares_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) -func request_Query_MegavaultOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryMegavaultOwnerSharesRequest +func request_Query_MegavaultAllOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultAllOwnerSharesRequest var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultOwnerShares_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultAllOwnerShares_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MegavaultOwnerShares(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.MegavaultAllOwnerShares(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_MegavaultOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryMegavaultOwnerSharesRequest +func local_request_Query_MegavaultAllOwnerShares_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMegavaultAllOwnerSharesRequest var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultOwnerShares_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MegavaultAllOwnerShares_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MegavaultOwnerShares(ctx, &protoReq) + msg, err := server.MegavaultAllOwnerShares(ctx, &protoReq) return msg, metadata, err } @@ -462,6 +516,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_MegavaultAllOwnerShares_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_MegavaultAllOwnerShares_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MegavaultAllOwnerShares_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_VaultParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -649,6 +726,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_MegavaultAllOwnerShares_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_MegavaultAllOwnerShares_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_MegavaultAllOwnerShares_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_VaultParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -701,7 +798,9 @@ var ( pattern_Query_MegavaultTotalShares_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"dydxprotocol", "vault", "megavault", "total_shares"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_MegavaultOwnerShares_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"dydxprotocol", "vault", "megavault", "owner_shares"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_MegavaultOwnerShares_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"dydxprotocol", "vault", "megavault", "owner_shares", "address"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_MegavaultAllOwnerShares_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"dydxprotocol", "vault", "megavault", "all_owner_shares"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_VaultParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"dydxprotocol", "vault", "params", "type", "number"}, "", runtime.AssumeColonVerbOpt(false))) @@ -719,6 +818,8 @@ var ( forward_Query_MegavaultOwnerShares_0 = runtime.ForwardResponseMessage + forward_Query_MegavaultAllOwnerShares_0 = runtime.ForwardResponseMessage + forward_Query_VaultParams_0 = runtime.ForwardResponseMessage forward_Query_MegavaultWithdrawalInfo_0 = runtime.ForwardResponseMessage From 61973446e764312618de720b12f8b05c6a9cba44 Mon Sep 17 00:00:00 2001 From: sr33j Date: Mon, 23 Sep 2024 17:32:22 -0400 Subject: [PATCH 04/10] Sp/vault post only orders (#2297) Co-authored-by: Tian Qin --- protocol/x/vault/keeper/orders.go | 8 ++++ protocol/x/vault/keeper/orders_test.go | 52 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/protocol/x/vault/keeper/orders.go b/protocol/x/vault/keeper/orders.go index 1f184d9f76..3e59423f19 100644 --- a/protocol/x/vault/keeper/orders.go +++ b/protocol/x/vault/keeper/orders.go @@ -344,12 +344,20 @@ func (k Keeper) GetVaultClobOrders( maxSubticks, ) + // If the side would increase the vault's inventory, make the order post-only. + timeInForceType := clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED + if (side == clobtypes.Order_SIDE_SELL && leveragePpm.Sign() <= 0) || + (side == clobtypes.Order_SIDE_BUY && leveragePpm.Sign() >= 0) { + timeInForceType = clobtypes.Order_TIME_IN_FORCE_POST_ONLY + } + return &clobtypes.Order{ OrderId: *orderId, Side: side, Quantums: orderSize.Uint64(), // Validated to be a uint64 above. Subticks: subticksRounded, GoodTilOneof: goodTilBlockTime, + TimeInForce: timeInForceType, } } diff --git a/protocol/x/vault/keeper/orders_test.go b/protocol/x/vault/keeper/orders_test.go index e7941f4585..5e631e0b20 100644 --- a/protocol/x/vault/keeper/orders_test.go +++ b/protocol/x/vault/keeper/orders_test.go @@ -1025,6 +1025,7 @@ func TestGetVaultClobOrders(t *testing.T) { expectedOrderSides []clobtypes.Order_Side expectedOrderSubticks []uint64 expectedOrderQuantums []uint64 + expectedTimeInForce []clobtypes.Order_TimeInForce expectedErr error }{ "Success - Vault Clob 0, quoting status, 2 layers, leverage 0, doesn't cross oracle price": { @@ -1108,6 +1109,14 @@ func TestGetVaultClobOrders(t *testing.T) { 20_000_000_000, 20_000_000_000, }, + // post-only if increases inventory + // vault is flat, all orders should be post-only + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + }, }, "Success - Vault Clob 1, quoting status, 3 layers, leverage -0.6, doesn't cross oracle price": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1198,6 +1207,16 @@ func TestGetVaultClobOrders(t *testing.T) { 41_666_000, 41_666_000, }, + // post-only if increases inventory + // vault is short, sell orders should be post-only + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + }, }, "Success - Vault Clob 1, quoting status, 3 layers, leverage -3, crosses oracle price": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1288,6 +1307,16 @@ func TestGetVaultClobOrders(t *testing.T) { 33_333_000, 33_333_000, }, + // post-only if increases inventory + // vault is short, sell orders should be post-only + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + }, }, "Success - Vault Clob 1, quoting status, 2 layers, leverage 3, crosses oracle price": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1364,6 +1393,14 @@ func TestGetVaultClobOrders(t *testing.T) { 333_333_000, 333_333_000, }, + // post-only if increases inventory + // vault is long, buy orders should be post-only + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_POST_ONLY, + }, }, "Success - Vault Clob 1, close-only status, 3 layers, leverage -0.6, buy orders only": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY, @@ -1434,6 +1471,11 @@ func TestGetVaultClobOrders(t *testing.T) { 41_666_000, 41_666_000, }, + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + }, }, "Success - Vault Clob 1, close-only status, 3 layers, leverage -0.6, no orders as size is rounded to 0": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY, @@ -1530,6 +1572,10 @@ func TestGetVaultClobOrders(t *testing.T) { 250_000_000, 250_000_000, }, + expectedTimeInForce: []clobtypes.Order_TimeInForce{ + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED, + }, }, "Success - Get orders from Vault for Clob Pair 1, No Orders due to Zero Order Size": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1557,6 +1603,7 @@ func TestGetVaultClobOrders(t *testing.T) { // round down to nearest multiple of step_base_quantums=1_000. // order size is 0. expectedOrderQuantums: []uint64{}, + expectedTimeInForce: []clobtypes.Order_TimeInForce{}, }, "Success - Clob Pair doesn't exist, Empty orders": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1570,6 +1617,7 @@ func TestGetVaultClobOrders(t *testing.T) { expectedOrderSides: []clobtypes.Order_Side{}, expectedOrderSubticks: []uint64{}, expectedOrderQuantums: []uint64{}, + expectedTimeInForce: []clobtypes.Order_TimeInForce{}, }, "Success - Clob Pair in status final settlement, Empty orders": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1636,6 +1684,7 @@ func TestGetVaultClobOrders(t *testing.T) { expectedOrderSides: []clobtypes.Order_Side{}, expectedOrderSubticks: []uint64{}, expectedOrderQuantums: []uint64{}, + expectedTimeInForce: []clobtypes.Order_TimeInForce{}, }, "Error - Vault equity is zero": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING, @@ -1775,6 +1824,7 @@ func TestGetVaultClobOrders(t *testing.T) { side clobtypes.Order_Side, quantums uint64, subticks uint64, + timeInForce clobtypes.Order_TimeInForce, ) *clobtypes.Order { return &clobtypes.Order{ OrderId: clobtypes.OrderId{ @@ -1789,6 +1839,7 @@ func TestGetVaultClobOrders(t *testing.T) { GoodTilOneof: &clobtypes.Order_GoodTilBlockTime{ GoodTilBlockTime: uint32(ctx.BlockTime().Unix()) + tc.vaultQuotingParams.OrderExpirationSeconds, }, + TimeInForce: timeInForce, } } expectedOrders := make([]*clobtypes.Order, 0) @@ -1800,6 +1851,7 @@ func TestGetVaultClobOrders(t *testing.T) { tc.expectedOrderSides[i], tc.expectedOrderQuantums[i], tc.expectedOrderSubticks[i], + tc.expectedTimeInForce[i], ), ) } From b0034d0c16dd82cc75077ed9a30fb4291ed31a34 Mon Sep 17 00:00:00 2001 From: shrenujb <98204323+shrenujb@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:17:49 -0400 Subject: [PATCH 05/10] Add TransferToVault keeper method (#2327) Signed-off-by: Shrenuj Bansal --- .../keeper/msg_server_allocate_to_vault.go | 39 +-------------- protocol/x/vault/keeper/vault.go | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/protocol/x/vault/keeper/msg_server_allocate_to_vault.go b/protocol/x/vault/keeper/msg_server_allocate_to_vault.go index 491103ddf4..2691e48673 100644 --- a/protocol/x/vault/keeper/msg_server_allocate_to_vault.go +++ b/protocol/x/vault/keeper/msg_server_allocate_to_vault.go @@ -6,9 +6,6 @@ import ( errorsmod "cosmossdk.io/errors" "github.com/dydxprotocol/v4-chain/protocol/lib" - assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" - clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" - sendingtypes "github.com/dydxprotocol/v4-chain/protocol/x/sending/types" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -29,40 +26,8 @@ func (k msgServer) AllocateToVault( ) } - // Check if vault has a corresponding clob pair. - _, exists := k.Keeper.clobKeeper.GetClobPair(ctx, clobtypes.ClobPairId(msg.VaultId.Number)) - if !exists { - return nil, types.ErrClobPairNotFound - } - - // If vault doesn't exist: - // 1. initialize params with `STAND_BY` status. - // 2. add vault to address store. - _, exists = k.Keeper.GetVaultParams(ctx, msg.VaultId) - if !exists { - err := k.Keeper.SetVaultParams( - ctx, - msg.VaultId, - types.VaultParams{ - Status: types.VaultStatus_VAULT_STATUS_STAND_BY, - }, - ) - if err != nil { - return nil, err - } - k.Keeper.AddVaultToAddressStore(ctx, msg.VaultId) - } - - // Transfer from main vault to the specified vault. - if err := k.Keeper.sendingKeeper.ProcessTransfer( - ctx, - &sendingtypes.Transfer{ - Sender: types.MegavaultMainSubaccount, - Recipient: *msg.VaultId.ToSubaccountId(), - AssetId: assetstypes.AssetUsdc.Id, - Amount: msg.QuoteQuantums.BigInt().Uint64(), // validated to be positive above. - }, - ); err != nil { + err := k.Keeper.AllocateToVault(ctx, msg.VaultId, msg.QuoteQuantums.BigInt()) + if err != nil { return nil, err } diff --git a/protocol/x/vault/keeper/vault.go b/protocol/x/vault/keeper/vault.go index 19e883f168..1187a9c740 100644 --- a/protocol/x/vault/keeper/vault.go +++ b/protocol/x/vault/keeper/vault.go @@ -4,6 +4,10 @@ import ( "fmt" "math/big" + sendingtypes "github.com/dydxprotocol/v4-chain/protocol/x/sending/types" + + assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" + errorsmod "cosmossdk.io/errors" "cosmossdk.io/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -281,3 +285,48 @@ func (k Keeper) GetAllVaults(ctx sdk.Context) []types.Vault { } return vaults } + +// AllocateToVault transfers funds from main vault to a specified vault. +func (k Keeper) AllocateToVault( + ctx sdk.Context, + vaultId types.VaultId, + quantums *big.Int, +) error { + // Check if vault has a corresponding clob pair. + _, exists := k.clobKeeper.GetClobPair(ctx, clobtypes.ClobPairId(vaultId.Number)) + if !exists { + return types.ErrClobPairNotFound + } + + // If vault doesn't exist: + // 1. initialize params with `STAND_BY` status. + // 2. add vault to address store. + _, exists = k.GetVaultParams(ctx, vaultId) + if !exists { + err := k.SetVaultParams( + ctx, + vaultId, + types.VaultParams{ + Status: types.VaultStatus_VAULT_STATUS_STAND_BY, + }, + ) + if err != nil { + return err + } + k.AddVaultToAddressStore(ctx, vaultId) + } + + // Transfer from main vault to the specified vault. + if err := k.sendingKeeper.ProcessTransfer( + ctx, + &sendingtypes.Transfer{ + Sender: types.MegavaultMainSubaccount, + Recipient: *vaultId.ToSubaccountId(), + AssetId: assetstypes.AssetUsdc.Id, + Amount: quantums.Uint64(), // validated to be positive above. + }, + ); err != nil { + return err + } + return nil +} From cc59dd2263aaec81f92aaa98eb598c7baf29d536 Mon Sep 17 00:00:00 2001 From: Mohammed Affan Date: Mon, 23 Sep 2024 21:57:05 -0400 Subject: [PATCH 06/10] [OTE-817] update trading rewards with new logic (#2300) Co-authored-by: Teddy Ding --- .../trading_rewards/trading_rewards_test.go | 63 ++++++++-------- protocol/x/revshare/keeper/revshare.go | 2 +- protocol/x/revshare/keeper/revshare_test.go | 2 +- protocol/x/revshare/types/constants.go | 4 +- protocol/x/rewards/keeper/keeper.go | 24 ++++-- protocol/x/rewards/keeper/keeper_test.go | 75 +++++++++++++++++-- 6 files changed, 122 insertions(+), 48 deletions(-) diff --git a/protocol/testing/e2e/trading_rewards/trading_rewards_test.go b/protocol/testing/e2e/trading_rewards/trading_rewards_test.go index 9541d84054..dff299c7ab 100644 --- a/protocol/testing/e2e/trading_rewards/trading_rewards_test.go +++ b/protocol/testing/e2e/trading_rewards/trading_rewards_test.go @@ -1,13 +1,14 @@ package trading_rewards_test import ( - sdkmath "cosmossdk.io/math" - "github.com/cosmos/gogoproto/proto" - "github.com/dydxprotocol/v4-chain/protocol/app/flags" "math/big" "testing" "time" + sdkmath "cosmossdk.io/math" + "github.com/cosmos/gogoproto/proto" + "github.com/dydxprotocol/v4-chain/protocol/app/flags" + "github.com/cometbft/cometbft/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -229,20 +230,20 @@ func TestTradingRewards(t *testing.T) { }, { AccAddress: RewardsTreasuryAccAddress, - // Total of ~5.06 full coins have vested, which is less than calculated - // rewards (~5.5 full coins). So all reward tokens were distributed. + // Total of ~5.06 full coins have vested, calculated rewards are + // ~1.99 full coins. So remaining rewards are ~3.07 full coins. Balance: big_testutil.MustFirst(new(big.Int).SetString( - "0", + "3077645653924902967", 10, )), }, { AccAddress: constants.AliceAccAddress, - // starting balance + ~5.06 full coins rewards + // starting balance + ~1.99 full coins rewards Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "5068012730847979890", + "1990367076923076923", 10, )), ), @@ -258,7 +259,7 @@ func TestTradingRewards(t *testing.T) { TradingRewards: []*indexerevents.AddressTradingReward{ { Owner: constants.AliceAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(5068012730847979890), + DenomAmount: dtypes.NewIntFromUint64(1990367076923076923), }, }, }, @@ -277,10 +278,10 @@ func TestTradingRewards(t *testing.T) { }, { AccAddress: RewardsTreasuryAccAddress, - // ~25.34 full coins. Note this is exactly 10x the amount vested per block, + // balance + ~25.34 full coins. Note this is exactly 10x the amount vested per block, // since 10 blocks has passed since the last check. Balance: big_testutil.MustFirst(new(big.Int).SetString( - "25340063654239899450", + "28417709308164802417", 10, )), }, @@ -300,23 +301,23 @@ func TestTradingRewards(t *testing.T) { { AccAddress: constants.BobAccAddress, // Starting balance: 500000000000000000000000 - // Total rewards = (TakerFee - TakerVolume * MaxMakerRebate) * 0.99 - // = ($28003 * 0.05% - $28003 * 0.011%) * 0.99 - // = ($14.0015 - $3.08033) 0.99 = $10.8119583 - // Reward tokens = $10.8119583 / $1.95 = 5.544594 full coins + // Total rewards = (TakerFee - TakerVolume * MaxMakerRebate - (takerFee * MaxPossibleTakerFeeRevShare)) * 0.99 + // = ($28003 * 0.05% - $28003 * 0.011% - $28003 * 0.05% * 0.5) * 0.99 + // = ($14.0015 - $3.08033 - $7.00075) 0.99 = $3.8812158 + // Reward tokens = $3.8812158 / $1.95 = 1.9903670769 full coins Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "5544594000000000000", + "1990367076923076923", 10, )), ), }, { AccAddress: RewardsTreasuryAccAddress, - // 25.34 + 2.534 - 5.544594 ~= 22.329 full coins + // balance + 25.34 + 2.534 - 1.9903670769 ~= 22.329 full coins Balance: big_testutil.MustFirst(new(big.Int).SetString( - "22329476019663889395", + "28961348596665715439", 10, )), }, @@ -326,7 +327,7 @@ func TestTradingRewards(t *testing.T) { TradingRewards: []*indexerevents.AddressTradingReward{ { Owner: constants.BobAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(5544594000000000000), + DenomAmount: dtypes.NewIntFromUint64(1990367076923076923), }, }, }, @@ -482,8 +483,8 @@ func TestTradingRewards(t *testing.T) { // - Carl and Dave: $12.519 // Total rewards tokens distributed: ~25.34 (less than the value of net fees) // Entitled reward tokens: - // - Alice and Bob: 8.0539 - // - Carl and Dave: 4.616 + // - Alice and Bob: 3.98073 + // - Carl and Dave: 2.28156 ExpectedBalances: []expectedBalance{ { AccAddress: RewardsVesterAccAddress, @@ -495,9 +496,9 @@ func TestTradingRewards(t *testing.T) { }, { AccAddress: RewardsTreasuryAccAddress, - // All vested rewards were distributed, only rounding dusts left. + // 12.52458 full coins distributed, ~12.815 full coins remaining Balance: big_testutil.MustFirst(new(big.Int).SetString( - "2", + "12815456885009130222", 10, )), }, @@ -506,7 +507,7 @@ func TestTradingRewards(t *testing.T) { Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "8053910091363583686", + "3980734153846153845", 10, )), ), @@ -516,7 +517,7 @@ func TestTradingRewards(t *testing.T) { Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "8053910091363583686", + "3980734153846153845", 10, )), ), @@ -526,7 +527,7 @@ func TestTradingRewards(t *testing.T) { Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "4616121735756366038", + "2281569230769230769", 10, )), ), @@ -536,7 +537,7 @@ func TestTradingRewards(t *testing.T) { Balance: new(big.Int).Add( TestAccountStartingTokenBalance, big_testutil.MustFirst(new(big.Int).SetString( - "4616121735756366038", + "2281569230769230769", 10, )), ), @@ -547,19 +548,19 @@ func TestTradingRewards(t *testing.T) { TradingRewards: []*indexerevents.AddressTradingReward{ { Owner: constants.BobAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(8053910091363583686), + DenomAmount: dtypes.NewIntFromUint64(3980734153846153845), }, { Owner: constants.AliceAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(8053910091363583686), + DenomAmount: dtypes.NewIntFromUint64(3980734153846153845), }, { Owner: constants.CarlAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(4616121735756366038), + DenomAmount: dtypes.NewIntFromUint64(2281569230769230769), }, { Owner: constants.DaveAccAddress.String(), - DenomAmount: dtypes.NewIntFromUint64(4616121735756366038), + DenomAmount: dtypes.NewIntFromUint64(2281569230769230769), }, }, }, diff --git a/protocol/x/revshare/keeper/revshare.go b/protocol/x/revshare/keeper/revshare.go index 5a50f4efcd..91d67df6c9 100644 --- a/protocol/x/revshare/keeper/revshare.go +++ b/protocol/x/revshare/keeper/revshare.go @@ -227,7 +227,7 @@ func (k Keeper) getAffiliateRevShares( ) ([]types.RevShare, error) { takerAddr := fill.TakerAddr takerFee := fill.TakerFeeQuoteQuantums - if fill.MonthlyRollingTakerVolumeQuantums >= types.Max30dRefereeVolumeQuantums { + if fill.MonthlyRollingTakerVolumeQuantums >= types.MaxReferee30dVolumeForAffiliateShareQuantums { return nil, nil } diff --git a/protocol/x/revshare/keeper/revshare_test.go b/protocol/x/revshare/keeper/revshare_test.go index 6182ead2a0..7ecc596393 100644 --- a/protocol/x/revshare/keeper/revshare_test.go +++ b/protocol/x/revshare/keeper/revshare_test.go @@ -504,7 +504,7 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { MakerFeeQuoteQuantums: big.NewInt(2_000_000), FillQuoteQuantums: big.NewInt(100_000_000_000), ProductId: perpetualId, - MonthlyRollingTakerVolumeQuantums: types.Max30dRefereeVolumeQuantums + 1, + MonthlyRollingTakerVolumeQuantums: types.MaxReferee30dVolumeForAffiliateShareQuantums + 1, MarketId: marketId, }, expectedRevSharesForFill: types.RevSharesForFill{ diff --git a/protocol/x/revshare/types/constants.go b/protocol/x/revshare/types/constants.go index 4c13aa349e..d88c519943 100644 --- a/protocol/x/revshare/types/constants.go +++ b/protocol/x/revshare/types/constants.go @@ -1,6 +1,6 @@ package types const ( - // 25 million USDC - Max30dRefereeVolumeQuantums = uint64(25_000_000_000_000) + // 50 million USDC + MaxReferee30dVolumeForAffiliateShareQuantums = uint64(50_000_000_000_000) ) diff --git a/protocol/x/rewards/keeper/keeper.go b/protocol/x/rewards/keeper/keeper.go index 14f14d1aa7..f9daa60fac 100644 --- a/protocol/x/rewards/keeper/keeper.go +++ b/protocol/x/rewards/keeper/keeper.go @@ -19,6 +19,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/lib/log" "github.com/dydxprotocol/v4-chain/protocol/lib/metrics" + affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" "github.com/dydxprotocol/v4-chain/protocol/x/rewards/types" @@ -120,15 +121,20 @@ func (k Keeper) GetRewardShare( // // Within each block, total reward share score for an address is defined as: // -// reward_share_score = total_taker_fees_paid - total_rev_shared_taker_fee +// reward_share_score = total_taker_fees_paid - max_possible_taker_fee_rev_share // - max_possible_maker_rebate * taker_volume + total_positive_maker_fees - total_rev_shared_maker_fee // // Hence, for each fill, increment reward share score as follow: // - Let F = sum(percentages of general rev-share) (excluding taker only rev share i.e. affiliate) // - For maker address, positive_maker_fees * (1 - F) are added to reward share score. // - For taker address, (positive_taker_fees - max_possible_maker_rebate -// * fill_quote_quantum - taker_fee_rev_share) * (1 - F) +// * fill_quote_quantum - max_possible_taker_fee_rev_share) * (1 - F) // are added to reward share score. +// max_possible_taker_fee_rev_share is 0 when taker trailing volume is > MaxReferee30dVolumeForAffiliateShareQuantums, +// since taker_fee_share is only affiliate at the moment, and they don’t generate affiliate rev share. +// When taker volume ≤ MaxReferee30dVolumeForAffiliateShareQuantums, +// max_possible_taker_fee_rev_share = max_vip_affiliate_share * taker_fee +// regardless of if the taker has an affiliate or not. func (k Keeper) AddRewardSharesForFill( ctx sdk.Context, @@ -143,9 +149,15 @@ func (k Keeper) AddRewardSharesForFill( if value, ok := revSharesForFill.FeeSourceToRevSharePpm[revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE]; ok { totalNetFeeRevSharePpm = value } - totalTakerFeeRevShareQuantums := big.NewInt(0) - if value, ok := revSharesForFill.FeeSourceToQuoteQuantums[revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE]; ok { - totalTakerFeeRevShareQuantums = value + maxPossibleTakerFeeRevShare := big.NewInt(0) + + // taker revshare is always 0 if taker rolling volume is greater than or equal + // to Max30dTakerVolumeQuantums, so no need to reduce score by `max_possible_taker_fee_rev_share` + if fill.MonthlyRollingTakerVolumeQuantums < revsharetypes.MaxReferee30dVolumeForAffiliateShareQuantums { + maxPossibleTakerFeeRevShare = lib.BigMulPpm(fill.TakerFeeQuoteQuantums, + lib.BigU(affiliatetypes.AffiliatesRevSharePpmCap), + false, + ) } totalFeeSubNetRevSharePpm := lib.OneMillion - totalNetFeeRevSharePpm @@ -159,7 +171,7 @@ func (k Keeper) AddRewardSharesForFill( ) netTakerFee = netTakerFee.Sub( netTakerFee, - totalTakerFeeRevShareQuantums, + maxPossibleTakerFeeRevShare, ) takerWeight := lib.BigMulPpm( netTakerFee, diff --git a/protocol/x/rewards/keeper/keeper_test.go b/protocol/x/rewards/keeper/keeper_test.go index d41f89b738..5a018227f1 100644 --- a/protocol/x/rewards/keeper/keeper_test.go +++ b/protocol/x/rewards/keeper/keeper_test.go @@ -184,7 +184,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(1_200_000), // 2 - 0.1% * 800 + Weight: dtypes.NewInt(200_000), // 2 - 0.1% * 800 -(2 * 0.5) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -218,7 +218,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(1_250_000), // 2 - 0.1% * 750 + Weight: dtypes.NewInt(250_000), // 2 - 0.1% * 750 - (2 * 0.5) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -252,7 +252,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(1_625_000), // 2 - 0.05% * 750 + Weight: dtypes.NewInt(625_000), // 2 - 0.05% * 750 - (2 * 0.5) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -319,7 +319,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(700_000), + Weight: dtypes.NewInt(350_000), // 0.7 - (0.7 * 0.5) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -367,7 +367,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(1_080_000), // (2 - 0.1% * 800 - 0) * (1 - 0.1) + Weight: dtypes.NewInt(180_000), // (2 - 0.1% * 800 - 0.5*2) * (1 - 0.1) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -422,7 +422,7 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(960_000), // (2 - 0.1% * 800 - 0) * (1 - 0.2) + Weight: dtypes.NewInt(160_000), // (2 - 0.1% * 800 - 0.5*2) * (1 - 0.2) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, @@ -483,7 +483,68 @@ func TestAddRewardSharesForFill(t *testing.T) { }, expectedTakerShare: types.RewardShare{ Address: takerAddress, - Weight: dtypes.NewInt(900_000), // (2 - 0.1% * 800 - 0.2) * (1 - 0.1) + Weight: dtypes.NewInt(180_000), // (2 - 0.1% * 800 - 1) * (1 - 0.1) + }, + expectedMakerShare: types.RewardShare{ + Address: makerAddress, + Weight: dtypes.NewInt(900_000), // 1 * (1 - 0.1) + }, + }, + "positive maker + taker fees reduced by maker rebate, taker + net fee revshare,rolling taker volume > 50 mil": { + prevTakerRewardShare: nil, + prevMakerRewardShare: nil, + fill: clobtypes.FillForProcess{ + TakerAddr: takerAddress, + TakerFeeQuoteQuantums: big.NewInt(2_000_000), + MakerAddr: makerAddress, + MakerFeeQuoteQuantums: big.NewInt(1_000_000), + FillQuoteQuantums: big.NewInt(800_000_000), + ProductId: uint32(1), + MarketId: uint32(1), + MonthlyRollingTakerVolumeQuantums: 60_000_000_000_000, + }, + revSharesForFill: revsharetypes.RevSharesForFill{ + AllRevShares: []revsharetypes.RevShare{ + { + Recipient: constants.AliceAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, + QuoteQuantums: big.NewInt(200_000), + RevSharePpm: 100_000, // 10% + }, + { + Recipient: takerAddress, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE, + RevShareType: revsharetypes.REV_SHARE_TYPE_AFFILIATE, + QuoteQuantums: big.NewInt(200_000), + RevSharePpm: 100_000, // 10% + }, + }, + FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ + revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(200_000), + }, + FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ + revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 100_000, // 10% + }, + AffiliateRevShare: &revsharetypes.RevShare{ + Recipient: takerAddress, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE, + RevShareType: revsharetypes.REV_SHARE_TYPE_AFFILIATE, + QuoteQuantums: big.NewInt(200_000), + RevSharePpm: 100_000, // 10% + }, + }, + feeTiers: []*feetierstypes.PerpetualFeeTier{ + { + MakerFeePpm: -1_000, // -0.1% + TakerFeePpm: 2_000, // 0.2% + }, + }, + expectedTakerShare: types.RewardShare{ + Address: takerAddress, + Weight: dtypes.NewInt(1_080_000), // (2 - 0.1% * 800 - 0) * (1 - 0.1) }, expectedMakerShare: types.RewardShare{ Address: makerAddress, From 1659f9355964d005dc79398bd8c29b5de98cb903 Mon Sep 17 00:00:00 2001 From: Mohammed Affan Date: Mon, 23 Sep 2024 22:39:31 -0400 Subject: [PATCH 07/10] [OTE-816] Update Revshare logic for affiliates (#2298) --- protocol/app/app.go | 1 - protocol/testutil/keeper/clob.go | 1 - protocol/testutil/keeper/listing.go | 1 - protocol/testutil/keeper/sending.go | 1 - protocol/testutil/keeper/subaccounts.go | 3 - .../x/clob/keeper/process_single_match.go | 10 +- protocol/x/revshare/keeper/revshare.go | 41 +-- protocol/x/revshare/keeper/revshare_test.go | 170 ++++------ protocol/x/revshare/types/errors.go | 5 + protocol/x/revshare/types/types.go | 2 +- protocol/x/rewards/keeper/keeper.go | 2 +- protocol/x/rewards/keeper/keeper_test.go | 42 +-- protocol/x/subaccounts/keeper/keeper.go | 4 +- protocol/x/subaccounts/keeper/transfer.go | 3 +- .../x/subaccounts/keeper/transfer_test.go | 290 ++++++++---------- .../x/subaccounts/types/expected_keepers.go | 11 - 16 files changed, 245 insertions(+), 342 deletions(-) diff --git a/protocol/app/app.go b/protocol/app/app.go index d06428fb23..d45290bc17 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -1091,7 +1091,6 @@ func New( app.BankKeeper, app.PerpetualsKeeper, app.BlockTimeKeeper, - app.RevShareKeeper, app.IndexerEventManager, app.FullNodeStreamingManager, ) diff --git a/protocol/testutil/keeper/clob.go b/protocol/testutil/keeper/clob.go index 0b75109217..0e544921df 100644 --- a/protocol/testutil/keeper/clob.go +++ b/protocol/testutil/keeper/clob.go @@ -170,7 +170,6 @@ func NewClobKeepersTestContextWithUninitializedMemStore( bankKeeper, ks.PerpetualsKeeper, ks.BlockTimeKeeper, - revShareKeeper, indexerEventsTransientStoreKey, true, ) diff --git a/protocol/testutil/keeper/listing.go b/protocol/testutil/keeper/listing.go index d09633c4cd..7b34551a2a 100644 --- a/protocol/testutil/keeper/listing.go +++ b/protocol/testutil/keeper/listing.go @@ -134,7 +134,6 @@ func ListingKeepers( bankKeeper, perpetualsKeeper, blockTimeKeeper, - revShareKeeper, transientStoreKey, true, ) diff --git a/protocol/testutil/keeper/sending.go b/protocol/testutil/keeper/sending.go index 9661da1107..7adb413cc2 100644 --- a/protocol/testutil/keeper/sending.go +++ b/protocol/testutil/keeper/sending.go @@ -113,7 +113,6 @@ func SendingKeepersWithSubaccountsKeeper(t testing.TB, saKeeper types.Subaccount ks.BankKeeper, ks.PerpetualsKeeper, blockTimeKeeper, - revShareKeeper, transientStoreKey, true, ) diff --git a/protocol/testutil/keeper/subaccounts.go b/protocol/testutil/keeper/subaccounts.go index 51df4c148e..127cdf60ac 100644 --- a/protocol/testutil/keeper/subaccounts.go +++ b/protocol/testutil/keeper/subaccounts.go @@ -100,7 +100,6 @@ func SubaccountsKeepers(t testing.TB, msgSenderEnabled bool) ( bankKeeper, perpetualsKeeper, blocktimeKeeper, - revShareKeeper, transientStoreKey, msgSenderEnabled, ) @@ -132,7 +131,6 @@ func createSubaccountsKeeper( bk types.BankKeeper, pk *perpskeeper.Keeper, btk *blocktimekeeper.Keeper, - rsk *revsharekeeper.Keeper, transientStoreKey storetypes.StoreKey, msgSenderEnabled bool, ) (*keeper.Keeper, storetypes.StoreKey) { @@ -151,7 +149,6 @@ func createSubaccountsKeeper( bk, pk, btk, - rsk, mockIndexerEventsManager, streaming.NewNoopGrpcStreamingManager(), ) diff --git a/protocol/x/clob/keeper/process_single_match.go b/protocol/x/clob/keeper/process_single_match.go index 509a5ccfc0..903e351928 100644 --- a/protocol/x/clob/keeper/process_single_match.go +++ b/protocol/x/clob/keeper/process_single_match.go @@ -14,6 +14,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/lib/metrics" assettypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" gometrics "github.com/hashicorp/go-metrics" ) @@ -464,14 +465,13 @@ func (k Keeper) persistMatchedOrders( // Distribute the fee amount from subacounts module to fee collector and rev share accounts bigTotalFeeQuoteQuantums := new(big.Int).Add(bigTakerFeeQuoteQuantums, bigMakerFeeQuoteQuantums) revSharesForFill, err := k.revshareKeeper.GetAllRevShares(ctx, fillForProcess, affiliatesWhitelistMap) - + if err != nil { + revSharesForFill = revsharetypes.RevSharesForFill{} + log.ErrorLog(ctx, "error getting rev shares for fill", "error", err) + } if revSharesForFill.AffiliateRevShare != nil { affiliateRevSharesQuoteQuantums = revSharesForFill.AffiliateRevShare.QuoteQuantums } - - if err != nil { - return takerUpdateResult, makerUpdateResult, affiliateRevSharesQuoteQuantums, err - } if err := k.subaccountsKeeper.DistributeFees( ctx, assettypes.AssetUsdc.Id, diff --git a/protocol/x/revshare/keeper/revshare.go b/protocol/x/revshare/keeper/revshare.go index 91d67df6c9..74ea0c0158 100644 --- a/protocol/x/revshare/keeper/revshare.go +++ b/protocol/x/revshare/keeper/revshare.go @@ -3,7 +3,6 @@ package keeper import ( "math/big" - errorsmod "cosmossdk.io/errors" "cosmossdk.io/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/lib" @@ -163,25 +162,28 @@ func (k Keeper) GetAllRevShares( feeSourceToRevSharePpm := make(map[types.RevShareFeeSource]uint32) feeSourceToQuoteQuantums[types.REV_SHARE_FEE_SOURCE_TAKER_FEE] = big.NewInt(0) feeSourceToRevSharePpm[types.REV_SHARE_FEE_SOURCE_TAKER_FEE] = 0 - feeSourceToQuoteQuantums[types.REV_SHARE_FEE_SOURCE_NET_FEE] = big.NewInt(0) - feeSourceToRevSharePpm[types.REV_SHARE_FEE_SOURCE_NET_FEE] = 0 + feeSourceToQuoteQuantums[types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE] = big.NewInt(0) + feeSourceToRevSharePpm[types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE] = 0 totalFeesShared := big.NewInt(0) takerFees := fill.TakerFeeQuoteQuantums makerFees := fill.MakerFeeQuoteQuantums netFees := big.NewInt(0).Add(takerFees, makerFees) - affiliateRevShares, err := k.getAffiliateRevShares(ctx, fill, affiliatesWhitelistMap) + affiliateRevShares, affiliateFeesShared, err := k.getAffiliateRevShares(ctx, fill, affiliatesWhitelistMap) if err != nil { return types.RevSharesForFill{}, err } + netFeesSubAffiliateFeesShared := new(big.Int).Sub(netFees, affiliateFeesShared) + if netFeesSubAffiliateFeesShared.Sign() <= 0 { + return types.RevSharesForFill{}, types.ErrAffiliateFeesSharedExceedsNetFees + } - unconditionalRevShares, err := k.getUnconditionalRevShares(ctx, netFees) + unconditionalRevShares, err := k.getUnconditionalRevShares(ctx, netFeesSubAffiliateFeesShared) if err != nil { return types.RevSharesForFill{}, err } - - marketMapperRevShares, err := k.getMarketMapperRevShare(ctx, fill.MarketId, netFees) + marketMapperRevShares, err := k.getMarketMapperRevShare(ctx, fill.MarketId, netFeesSubAffiliateFeesShared) if err != nil { return types.RevSharesForFill{}, err } @@ -208,8 +210,7 @@ func (k Keeper) GetAllRevShares( } //check total fees shared is less than or equal to net fees if totalFeesShared.Cmp(netFees) > 0 { - return types.RevSharesForFill{}, errorsmod.Wrap( - types.ErrTotalFeesSharedExceedsNetFees, "total fees shared exceeds net fees") + return types.RevSharesForFill{}, types.ErrTotalFeesSharedExceedsNetFees } return types.RevSharesForFill{ @@ -224,20 +225,20 @@ func (k Keeper) getAffiliateRevShares( ctx sdk.Context, fill clobtypes.FillForProcess, affiliatesWhitelistMap map[string]uint32, -) ([]types.RevShare, error) { +) ([]types.RevShare, *big.Int, error) { takerAddr := fill.TakerAddr takerFee := fill.TakerFeeQuoteQuantums if fill.MonthlyRollingTakerVolumeQuantums >= types.MaxReferee30dVolumeForAffiliateShareQuantums { - return nil, nil + return nil, big.NewInt(0), nil } takerAffiliateAddr, feeSharePpm, exists, err := k.affiliatesKeeper.GetTakerFeeShare( ctx, takerAddr, affiliatesWhitelistMap) if err != nil { - return nil, err + return nil, big.NewInt(0), err } if !exists { - return nil, nil + return nil, big.NewInt(0), nil } feesShared := lib.BigMulPpm(takerFee, lib.BigU(feeSharePpm), false) return []types.RevShare{ @@ -248,12 +249,12 @@ func (k Keeper) getAffiliateRevShares( QuoteQuantums: feesShared, RevSharePpm: feeSharePpm, }, - }, nil + }, feesShared, nil } func (k Keeper) getUnconditionalRevShares( ctx sdk.Context, - netFees *big.Int, + netFeesSubAffiliateFeesShared *big.Int, ) ([]types.RevShare, error) { revShares := []types.RevShare{} unconditionalRevShareConfig, err := k.GetUnconditionalRevShareConfigParams(ctx) @@ -261,10 +262,10 @@ func (k Keeper) getUnconditionalRevShares( return nil, err } for _, revShare := range unconditionalRevShareConfig.Configs { - feeShared := lib.BigMulPpm(netFees, lib.BigU(revShare.SharePpm), false) + feeShared := lib.BigMulPpm(netFeesSubAffiliateFeesShared, lib.BigU(revShare.SharePpm), false) revShare := types.RevShare{ Recipient: revShare.Address, - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: feeShared, RevSharePpm: revShare.SharePpm, @@ -277,7 +278,7 @@ func (k Keeper) getUnconditionalRevShares( func (k Keeper) getMarketMapperRevShare( ctx sdk.Context, marketId uint32, - netFees *big.Int, + netFeesSubAffiliateFeesShared *big.Int, ) ([]types.RevShare, error) { revShares := []types.RevShare{} marketMapperRevshareAddress, revenueSharePpm, err := k.GetMarketMapperRevenueShareForMarket(ctx, marketId) @@ -288,10 +289,10 @@ func (k Keeper) getMarketMapperRevShare( return nil, nil } - marketMapperRevshareAmount := lib.BigMulPpm(netFees, lib.BigU(revenueSharePpm), false) + marketMapperRevshareAmount := lib.BigMulPpm(netFeesSubAffiliateFeesShared, lib.BigU(revenueSharePpm), false) revShares = append(revShares, types.RevShare{ Recipient: marketMapperRevshareAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, QuoteQuantums: marketMapperRevshareAmount, RevSharePpm: revenueSharePpm, diff --git a/protocol/x/revshare/keeper/revshare_test.go b/protocol/x/revshare/keeper/revshare_test.go index 7ecc596393..488a908679 100644 --- a/protocol/x/revshare/keeper/revshare_test.go +++ b/protocol/x/revshare/keeper/revshare_test.go @@ -324,31 +324,34 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { expectedRevSharesForFill: types.RevSharesForFill{ AllRevShares: []types.RevShare{ { + // BobAddress has 500000000000000000000000 coins staked + // via genesis. Which puts Bob at the highest tier + // and gives him a 15% taker fee share. Recipient: constants.BobAccAddress.String(), RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_TAKER_FEE, RevShareType: types.REV_SHARE_TYPE_AFFILIATE, - QuoteQuantums: big.NewInt(1_500_000), + QuoteQuantums: big.NewInt(1_500_000), // 15 % of 10 million taker fee quote quantums RevSharePpm: 150_000, }, { Recipient: constants.BobAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, - QuoteQuantums: big.NewInt(2_400_000), + QuoteQuantums: big.NewInt(2_100_000), // (10 + 2 - 1.5) * 20% RevSharePpm: 200_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, - QuoteQuantums: big.NewInt(3_600_000), + QuoteQuantums: big.NewInt(3_150_000), // (10 + 2 - 1.5) * 30% RevSharePpm: 300_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, - QuoteQuantums: big.NewInt(1_200_000), + QuoteQuantums: big.NewInt(1_050_000), // (10 + 2 - 1.5) * 10% RevSharePpm: 100_000, }, }, @@ -356,16 +359,17 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { Recipient: constants.BobAccAddress.String(), RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_TAKER_FEE, RevShareType: types.REV_SHARE_TYPE_AFFILIATE, - QuoteQuantums: big.NewInt(1_500_000), + QuoteQuantums: big.NewInt(1_500_000), // 15 % of 10 million taker fee quote quantums RevSharePpm: 150_000, }, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(7_200_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), // affiliate rev share fees + // unconditional + market mapper rev shares fees + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(6_300_000), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, - types.REV_SHARE_FEE_SOURCE_NET_FEE: 600_000, + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, // affiliate rev share fee ppm + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 600_000, // unconditional + market mapper rev share fee ppm }, }, fill: clobtypes.FillForProcess{ @@ -408,7 +412,7 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, }, { - name: "Valid rev-share from affiliates, negative unconditional and market mapper", + name: "Valid rev-share from affiliates, negative maker fee and unconditional and market mapper", expectedRevSharesForFill: types.RevSharesForFill{ AllRevShares: []types.RevShare{ { @@ -420,33 +424,33 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, { Recipient: constants.BobAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, - QuoteQuantums: big.NewInt(1_600_000), + QuoteQuantums: big.NewInt(1_300_000), RevSharePpm: 200_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, - QuoteQuantums: big.NewInt(2_400_000), + QuoteQuantums: big.NewInt(1_950_000), RevSharePpm: 300_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, - QuoteQuantums: big.NewInt(800_000), + QuoteQuantums: big.NewInt(650_000), RevSharePpm: 100_000, }, }, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(4_800_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(3_900_000), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, - types.REV_SHARE_FEE_SOURCE_NET_FEE: 600_000, + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 600_000, }, AffiliateRevShare: &types.RevShare{ Recipient: constants.BobAccAddress.String(), @@ -511,21 +515,21 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { AllRevShares: []types.RevShare{ { Recipient: constants.BobAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(2_400_000), RevSharePpm: 200_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(3_600_000), RevSharePpm: 300_000, }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, QuoteQuantums: big.NewInt(1_200_000), RevSharePpm: 100_000, @@ -533,12 +537,12 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, AffiliateRevShare: nil, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(7_200_000), - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(7_200_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: 600_000, - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 600_000, + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, }, }, setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, @@ -582,19 +586,19 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, - QuoteQuantums: big.NewInt(1_200_000), + QuoteQuantums: big.NewInt(1_050_000), RevSharePpm: 100_000, // 10% }, }, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(1_200_000), - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(1_050_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, // 15% + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, // 15% }, AffiliateRevShare: &types.RevShare{ Recipient: constants.BobAccAddress.String(), @@ -643,19 +647,19 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, { Recipient: constants.BobAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, - QuoteQuantums: big.NewInt(2_400_000), + QuoteQuantums: big.NewInt(2_100_000), RevSharePpm: 200_000, // 20% }, }, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(2_400_000), - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(2_100_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(1_500_000), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: 200_000, // 20% - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, // 15% + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 200_000, // 20% + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 150_000, // 15% }, AffiliateRevShare: &types.RevShare{ Recipient: constants.BobAccAddress.String(), @@ -705,9 +709,9 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { }, { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, - QuoteQuantums: big.NewInt(1_200_000), + QuoteQuantums: big.NewInt(950_000), RevSharePpm: 100_000, // 10% }, }, @@ -719,12 +723,12 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { RevSharePpm: 250_000, // 25% }, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(1_200_000), - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(2_500_000), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(950_000), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(2_500_000), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 250_000, // 25% + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 250_000, // 25% }, }, fill: clobtypes.FillForProcess{ @@ -767,12 +771,12 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { AllRevShares: []types.RevShare{}, AffiliateRevShare: nil, FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(0), - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(0), + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), }, FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ - types.REV_SHARE_FEE_SOURCE_NET_FEE: 0, - types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 0, + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, }, }, fill: clobtypes.FillForProcess{ @@ -821,17 +825,17 @@ func TestKeeper_GetAllRevShares_Invalid(t *testing.T) { name string revenueSharePpmNetFees uint32 revenueSharePpmTakerFees uint32 - expectedError error monthlyRollingTakerVolumeQuantums uint64 + expectedError error setup func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, affiliatesKeeper *affiliateskeeper.Keeper) }{ { name: "Total fees shared exceeds net fees from all sources", - revenueSharePpmNetFees: 950_000, // 95%, - revenueSharePpmTakerFees: 150_000, // 15% - expectedError: types.ErrTotalFeesSharedExceedsNetFees, + revenueSharePpmNetFees: 950_000, // 95%, + revenueSharePpmTakerFees: 150_000, // 15% monthlyRollingTakerVolumeQuantums: 1_000_000_000_000, // 1 million USDC + expectedError: types.ErrTotalFeesSharedExceedsNetFees, setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, affiliatesKeeper *affiliateskeeper.Keeper) { err := keeper.SetMarketMapperRevenueShareParams(ctx, types.MarketMapperRevenueShareParams{ @@ -845,7 +849,7 @@ func TestKeeper_GetAllRevShares_Invalid(t *testing.T) { Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ { Address: constants.BobAccAddress.String(), - SharePpm: 150_000, // 15% + SharePpm: 250_000, // 25% }, }, }) @@ -856,58 +860,12 @@ func TestKeeper_GetAllRevShares_Invalid(t *testing.T) { require.NoError(t, err) }, }, - { - name: "Total fees shared exceeds net fees from market mapper and affiliates", - revenueSharePpmNetFees: 950_000, // 95%, - revenueSharePpmTakerFees: 150_000, // 15% - expectedError: types.ErrTotalFeesSharedExceedsNetFees, - monthlyRollingTakerVolumeQuantums: 1_000_000_000_000, // 1 million USDC - setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, - affiliatesKeeper *affiliateskeeper.Keeper) { - err := keeper.SetMarketMapperRevenueShareParams(ctx, types.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 950_000, // 95% - ValidDays: 1, - }) - require.NoError(t, err) - - err = affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) - require.NoError(t, err) - err = affiliatesKeeper.RegisterAffiliate(ctx, constants.AliceAccAddress.String(), - constants.BobAccAddress.String()) - require.NoError(t, err) - }, - }, - { - name: "Total fees shared exceeds net fees from affiliates and unconditional rev shares", - revenueSharePpmNetFees: 950_000, // 95%, - revenueSharePpmTakerFees: 150_000, // 15% - expectedError: types.ErrTotalFeesSharedExceedsNetFees, - monthlyRollingTakerVolumeQuantums: 1_000_000_000_000, // 1 million USDC - setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, - affiliatesKeeper *affiliateskeeper.Keeper) { - keeper.SetUnconditionalRevShareConfigParams(ctx, types.UnconditionalRevShareConfig{ - Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ - { - Address: constants.BobAccAddress.String(), - SharePpm: 950_000, // 95% - }, - }, - }) - - err := affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) - require.NoError(t, err) - err = affiliatesKeeper.RegisterAffiliate(ctx, constants.AliceAccAddress.String(), - constants.BobAccAddress.String()) - require.NoError(t, err) - }, - }, { name: "Total fees shared exceeds net fees - no affiliate rev shares", - revenueSharePpmNetFees: 1_150_000, // 115%, - revenueSharePpmTakerFees: 0, // 0% - expectedError: types.ErrTotalFeesSharedExceedsNetFees, + revenueSharePpmNetFees: 1_150_000, // 115%, + revenueSharePpmTakerFees: 0, // 0% monthlyRollingTakerVolumeQuantums: 1_000_000_000_000, // 1 million USDC + expectedError: types.ErrTotalFeesSharedExceedsNetFees, setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, affiliatesKeeper *affiliateskeeper.Keeper) { err := keeper.SetMarketMapperRevenueShareParams(ctx, types.MarketMapperRevenueShareParams{ diff --git a/protocol/x/revshare/types/errors.go b/protocol/x/revshare/types/errors.go index 59a45c415f..702ae92d15 100644 --- a/protocol/x/revshare/types/errors.go +++ b/protocol/x/revshare/types/errors.go @@ -36,4 +36,9 @@ var ( 6, "total fees shared exceeds net fees", ) + ErrAffiliateFeesSharedExceedsNetFees = errorsmod.Register( + ModuleName, + 7, + "affiliate fees shared exceeds net fees", + ) ) diff --git a/protocol/x/revshare/types/types.go b/protocol/x/revshare/types/types.go index c17a50584d..17ecd548a3 100644 --- a/protocol/x/revshare/types/types.go +++ b/protocol/x/revshare/types/types.go @@ -41,7 +41,7 @@ type RevShareFeeSource int const ( REV_SHARE_FEE_SOURCE_UNSPECIFIED RevShareFeeSource = iota - REV_SHARE_FEE_SOURCE_NET_FEE + REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE REV_SHARE_FEE_SOURCE_TAKER_FEE ) diff --git a/protocol/x/rewards/keeper/keeper.go b/protocol/x/rewards/keeper/keeper.go index f9daa60fac..ad15888005 100644 --- a/protocol/x/rewards/keeper/keeper.go +++ b/protocol/x/rewards/keeper/keeper.go @@ -146,7 +146,7 @@ func (k Keeper) AddRewardSharesForFill( maxMakerRebatePpm := lib.Min(int32(0), lowestMakerFee) totalNetFeeRevSharePpm := uint32(0) - if value, ok := revSharesForFill.FeeSourceToRevSharePpm[revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE]; ok { + if value, ok := revSharesForFill.FeeSourceToRevSharePpm[revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE]; ok { totalNetFeeRevSharePpm = value } maxPossibleTakerFeeRevShare := big.NewInt(0) diff --git a/protocol/x/rewards/keeper/keeper_test.go b/protocol/x/rewards/keeper/keeper_test.go index 5a018227f1..e5db22d37b 100644 --- a/protocol/x/rewards/keeper/keeper_test.go +++ b/protocol/x/rewards/keeper/keeper_test.go @@ -343,19 +343,19 @@ func TestAddRewardSharesForFill(t *testing.T) { AllRevShares: []revsharetypes.RevShare{ { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(200_000), RevSharePpm: 100_000, // 10% }, }, FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(200_000), - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), }, FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, }, AffiliateRevShare: nil, }, @@ -391,26 +391,26 @@ func TestAddRewardSharesForFill(t *testing.T) { AllRevShares: []revsharetypes.RevShare{ { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(200_000), RevSharePpm: 100_000, // 10% }, { Recipient: constants.BobAccAddress.String(), - RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(200_000), RevSharePpm: 100_000, // 10% }, }, FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(400_000), - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(400_000), + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), }, FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: 200_000, // 20% - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 200_000, // 20% + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, }, AffiliateRevShare: nil, }, @@ -446,7 +446,7 @@ func TestAddRewardSharesForFill(t *testing.T) { AllRevShares: []revsharetypes.RevShare{ { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(200_000), RevSharePpm: 100_000, // 10% @@ -460,12 +460,12 @@ func TestAddRewardSharesForFill(t *testing.T) { }, }, FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(200_000), - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(200_000), }, FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 100_000, // 10% }, AffiliateRevShare: &revsharetypes.RevShare{ Recipient: takerAddress, @@ -507,7 +507,7 @@ func TestAddRewardSharesForFill(t *testing.T) { AllRevShares: []revsharetypes.RevShare{ { Recipient: constants.AliceAccAddress.String(), - RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE, + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, QuoteQuantums: big.NewInt(200_000), RevSharePpm: 100_000, // 10% @@ -521,12 +521,12 @@ func TestAddRewardSharesForFill(t *testing.T) { }, }, FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: big.NewInt(200_000), - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(200_000), + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(200_000), }, FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ - revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE: 100_000, // 10% - revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 100_000, // 10% }, AffiliateRevShare: &revsharetypes.RevShare{ Recipient: takerAddress, diff --git a/protocol/x/subaccounts/keeper/keeper.go b/protocol/x/subaccounts/keeper/keeper.go index 1d82f9d1ea..d1727b7da5 100644 --- a/protocol/x/subaccounts/keeper/keeper.go +++ b/protocol/x/subaccounts/keeper/keeper.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + streamingtypes "github.com/dydxprotocol/v4-chain/protocol/streaming/types" "cosmossdk.io/log" @@ -20,7 +21,6 @@ type ( bankKeeper types.BankKeeper perpetualsKeeper types.PerpetualsKeeper blocktimeKeeper types.BlocktimeKeeper - revShareKeeper types.RevShareKeeper indexerEventManager indexer_manager.IndexerEventManager streamingManager streamingtypes.FullNodeStreamingManager } @@ -33,7 +33,6 @@ func NewKeeper( bankKeeper types.BankKeeper, perpetualsKeeper types.PerpetualsKeeper, blocktimeKeeper types.BlocktimeKeeper, - revShareKeeper types.RevShareKeeper, indexerEventManager indexer_manager.IndexerEventManager, streamingManager streamingtypes.FullNodeStreamingManager, ) *Keeper { @@ -44,7 +43,6 @@ func NewKeeper( bankKeeper: bankKeeper, perpetualsKeeper: perpetualsKeeper, blocktimeKeeper: blocktimeKeeper, - revShareKeeper: revShareKeeper, indexerEventManager: indexerEventManager, streamingManager: streamingManager, } diff --git a/protocol/x/subaccounts/keeper/transfer.go b/protocol/x/subaccounts/keeper/transfer.go index 5724fbd777..ecf79952be 100644 --- a/protocol/x/subaccounts/keeper/transfer.go +++ b/protocol/x/subaccounts/keeper/transfer.go @@ -268,7 +268,8 @@ func (k Keeper) DistributeFees( totalTakerFeeRevShareQuantums = value } totalNetFeeRevShareQuantums := big.NewInt(0) - if value, ok := revSharesForFill.FeeSourceToQuoteQuantums[revsharetypes.REV_SHARE_FEE_SOURCE_NET_FEE]; ok { + if value, ok := + revSharesForFill.FeeSourceToQuoteQuantums[revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE]; ok { totalNetFeeRevShareQuantums = value } diff --git a/protocol/x/subaccounts/keeper/transfer_test.go b/protocol/x/subaccounts/keeper/transfer_test.go index 6fc7e33117..eefe09c4d3 100644 --- a/protocol/x/subaccounts/keeper/transfer_test.go +++ b/protocol/x/subaccounts/keeper/transfer_test.go @@ -20,7 +20,6 @@ import ( keepertest "github.com/dydxprotocol/v4-chain/protocol/testutil/keeper" sample_testutil "github.com/dydxprotocol/v4-chain/protocol/testutil/sample" testutil "github.com/dydxprotocol/v4-chain/protocol/testutil/util" - affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" asstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" @@ -1172,8 +1171,6 @@ func TestTransferFundsFromSubaccountToSubaccount_Failure(t *testing.T) { } func TestDistributeFees(t *testing.T) { - refereeAccAddr := constants.AliceAccAddress.String() - defaultUnconditionalRevSharePpm := uint32(100_000) tests := map[string]struct { skipSetUpUsdc bool @@ -1190,11 +1187,7 @@ func TestDistributeFees(t *testing.T) { affiliateRevShareAcctAddr string marketMapperRevShareAcctAddr string unconditionalRevShareAcctAddr string - - // Revenue share details - revshareParams revsharetypes.MarketMapperRevenueShareParams - setRevenueShare bool - revShareExpiration int64 + revShare revsharetypes.RevSharesForFill // Expectations. expectedErr error @@ -1219,15 +1212,13 @@ func TestDistributeFees(t *testing.T) { MarketId: uint32(0), MonthlyRollingTakerVolumeQuantums: 1_000_000, }, - collateralPoolAddr: types.ModuleAddress, - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 - expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + collateralPoolAddr: types.ModuleAddress, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 + expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1249,15 +1240,13 @@ func TestDistributeFees(t *testing.T) { collateralPoolAddr: authtypes.NewModuleAddress( types.ModuleName + ":" + lib.IntToString(3), ), - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 - expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 - marketMapperAccBalance: big.NewInt(0), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 + expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 + marketMapperAccBalance: big.NewInt(0), + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1276,17 +1265,15 @@ func TestDistributeFees(t *testing.T) { MarketId: uint32(3), MonthlyRollingTakerVolumeQuantums: 1_000_000, }, - collateralPoolAddr: types.ModuleAddress, - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedSubaccountsModuleAccBalance: big.NewInt(300), - expectedFeeModuleAccBalance: big.NewInt(2500), - expectedErr: sdkerrors.ErrInsufficientFunds, - marketMapperAccBalance: big.NewInt(0), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + collateralPoolAddr: types.ModuleAddress, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedSubaccountsModuleAccBalance: big.NewInt(300), + expectedFeeModuleAccBalance: big.NewInt(2500), + expectedErr: sdkerrors.ErrInsufficientFunds, + marketMapperAccBalance: big.NewInt(0), + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1308,16 +1295,14 @@ func TestDistributeFees(t *testing.T) { collateralPoolAddr: authtypes.NewModuleAddress( types.ModuleName + ":" + lib.IntToString(3), ), - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedSubaccountsModuleAccBalance: big.NewInt(300), - expectedFeeModuleAccBalance: big.NewInt(2500), - expectedErr: sdkerrors.ErrInsufficientFunds, - marketMapperAccBalance: big.NewInt(0), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedSubaccountsModuleAccBalance: big.NewInt(300), + expectedFeeModuleAccBalance: big.NewInt(2500), + expectedErr: sdkerrors.ErrInsufficientFunds, + marketMapperAccBalance: big.NewInt(0), + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1337,17 +1322,15 @@ func TestDistributeFees(t *testing.T) { MarketId: uint32(3), MonthlyRollingTakerVolumeQuantums: 1_000_000, }, - collateralPoolAddr: types.ModuleAddress, - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedErr: asstypes.ErrAssetDoesNotExist, - expectedSubaccountsModuleAccBalance: big.NewInt(500), - expectedFeeModuleAccBalance: big.NewInt(1500), - marketMapperAccBalance: big.NewInt(0), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + collateralPoolAddr: types.ModuleAddress, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedErr: asstypes.ErrAssetDoesNotExist, + expectedSubaccountsModuleAccBalance: big.NewInt(500), + expectedFeeModuleAccBalance: big.NewInt(1500), + marketMapperAccBalance: big.NewInt(0), + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1366,17 +1349,15 @@ func TestDistributeFees(t *testing.T) { MarketId: uint32(3), MonthlyRollingTakerVolumeQuantums: 1_000_000, }, - collateralPoolAddr: types.ModuleAddress, - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedErr: types.ErrAssetTransferThroughBankNotImplemented, - expectedSubaccountsModuleAccBalance: big.NewInt(500), - expectedFeeModuleAccBalance: big.NewInt(1500), - marketMapperAccBalance: big.NewInt(0), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - }, + collateralPoolAddr: types.ModuleAddress, + affiliateRevShareAcctAddr: "", + marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), + unconditionalRevShareAcctAddr: "", + expectedErr: types.ErrAssetTransferThroughBankNotImplemented, + expectedSubaccountsModuleAccBalance: big.NewInt(500), + expectedFeeModuleAccBalance: big.NewInt(1500), + marketMapperAccBalance: big.NewInt(0), + revShare: revsharetypes.RevSharesForFill{}, expectedMarketMapperAccBalance: big.NewInt(0), expectedAffiliateAccBalance: big.NewInt(0), expectedUnconditionalRevShareAccBalance: big.NewInt(0), @@ -1407,48 +1388,26 @@ func TestDistributeFees(t *testing.T) { affiliateRevShareAcctAddr: "", marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), unconditionalRevShareAcctAddr: "", - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% - ValidDays: 240, - }, - setRevenueShare: true, - revShareExpiration: 100, - }, - "success - market mapper rev share expired": { - asset: *constants.Usdc, - feeModuleAccBalance: big.NewInt(2500), - subaccountModuleAccBalance: big.NewInt(600), - marketMapperAccBalance: big.NewInt(0), - fill: clobtypes.FillForProcess{ - TakerAddr: constants.AliceAccAddress.String(), - TakerFeeQuoteQuantums: big.NewInt(250), - MakerAddr: constants.BobAccAddress.String(), - MakerFeeQuoteQuantums: big.NewInt(250), - FillQuoteQuantums: big.NewInt(500), - ProductId: uint32(4), - MarketId: uint32(4), - MonthlyRollingTakerVolumeQuantums: 1_000_000, - }, - affiliateRevShareAcctAddr: "", - marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), - unconditionalRevShareAcctAddr: "", - expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 - expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 - expectedMarketMapperAccBalance: big.NewInt(0), - expectedAffiliateAccBalance: big.NewInt(0), - expectedUnconditionalRevShareAccBalance: big.NewInt(0), - collateralPoolAddr: authtypes.NewModuleAddress( - types.ModuleName + ":" + lib.IntToString(4), - ), - - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% - ValidDays: 240, + revShare: revsharetypes.RevSharesForFill{ + AffiliateRevShare: nil, + FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(50), + }, + FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, // 0% + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 100_000, // 10% + }, + AllRevShares: []revsharetypes.RevShare{ + { + Recipient: constants.AliceAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: revsharetypes.REV_SHARE_TYPE_MARKET_MAPPER, + QuoteQuantums: big.NewInt(50), + RevSharePpm: 100_000, // 10% + }, + }, }, - setRevenueShare: true, - revShareExpiration: -10, }, "success - market mapper rev share rounded down to 0": { asset: *constants.Usdc, @@ -1476,13 +1435,18 @@ func TestDistributeFees(t *testing.T) { affiliateRevShareAcctAddr: "", marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), unconditionalRevShareAcctAddr: "", - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% - ValidDays: 240, + revShare: revsharetypes.RevSharesForFill{ + AffiliateRevShare: nil, + FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(0), + }, + FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, // 0% + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 0, // 0% + }, + AllRevShares: []revsharetypes.RevShare{}, }, - setRevenueShare: true, - revShareExpiration: 100, }, "success - distribute fees to market mapper, unconditional rev share, affiliate and fee collector": { asset: *constants.Usdc, @@ -1500,23 +1464,56 @@ func TestDistributeFees(t *testing.T) { MonthlyRollingTakerVolumeQuantums: 1_000_000, }, expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 - expectedFeeModuleAccBalance: big.NewInt(2888), // 2500 + 500 - 50 - expectedMarketMapperAccBalance: big.NewInt(50), // 10% of 500 + expectedFeeModuleAccBalance: big.NewInt(2892), // 2500 + 500 - 108 + expectedMarketMapperAccBalance: big.NewInt(48), // 10% of 488 expectedAffiliateAccBalance: big.NewInt(12), // 5% of 250 - expectedUnconditionalRevShareAccBalance: big.NewInt(50), // 10% of 500 + expectedUnconditionalRevShareAccBalance: big.NewInt(48), // 10% of 488 collateralPoolAddr: authtypes.NewModuleAddress( types.ModuleName + ":" + lib.IntToString(4), ), affiliateRevShareAcctAddr: constants.BobAccAddress.String(), marketMapperRevShareAcctAddr: constants.AliceAccAddress.String(), unconditionalRevShareAcctAddr: constants.CarlAccAddress.String(), - revshareParams: revsharetypes.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% - ValidDays: 240, + revShare: revsharetypes.RevSharesForFill{ + AffiliateRevShare: &revsharetypes.RevShare{ + Recipient: constants.BobAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE, + RevShareType: revsharetypes.REV_SHARE_TYPE_AFFILIATE, + QuoteQuantums: big.NewInt(12), + RevSharePpm: 50_000, // 5% + }, + FeeSourceToQuoteQuantums: map[revsharetypes.RevShareFeeSource]*big.Int{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(12), + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(96), + }, + FeeSourceToRevSharePpm: map[revsharetypes.RevShareFeeSource]uint32{ + revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE: 50_000, // 5% + revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 200_000, // 20% + }, + AllRevShares: []revsharetypes.RevShare{ + { + Recipient: constants.BobAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_TAKER_FEE, + RevShareType: revsharetypes.REV_SHARE_TYPE_AFFILIATE, + QuoteQuantums: big.NewInt(12), + RevSharePpm: 50_000, // 5% + }, + { + Recipient: constants.AliceAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: revsharetypes.REV_SHARE_TYPE_MARKET_MAPPER, + QuoteQuantums: big.NewInt(48), + RevSharePpm: 100_000, // 10% + }, + { + Recipient: constants.CarlAccAddress.String(), + RevShareFeeSource: revsharetypes.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: revsharetypes.REV_SHARE_TYPE_UNCONDITIONAL, + QuoteQuantums: big.NewInt(48), + RevSharePpm: 100_000, // 10% + }, + }, }, - setRevenueShare: true, - revShareExpiration: 100, }, // TODO(DEC-715): Add more test for non-USDC assets, after asset update // is implemented. @@ -1525,7 +1522,7 @@ func TestDistributeFees(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { ctx, keeper, pricesKeeper, perpetualsKeeper, accountKeeper, - bankKeeper, assetsKeeper, _, revShareKeeper, affiliatesKeeper, _ := + bankKeeper, assetsKeeper, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) keepertest.CreateTestMarkets(t, ctx, pricesKeeper) keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) @@ -1609,46 +1606,7 @@ func TestDistributeFees(t *testing.T) { require.NoError(t, err) } - // Set market mapper revenue share - err = revShareKeeper.SetMarketMapperRevenueShareParams( - ctx, - tc.revshareParams, - ) - require.NoError(t, err) - - if tc.setRevenueShare { - revShareKeeper.SetMarketMapperRevShareDetails( - ctx, - tc.fill.MarketId, - revsharetypes.MarketMapperRevShareDetails{ - ExpirationTs: uint64(ctx.BlockTime().Unix() + tc.revShareExpiration), - }, - ) - } - err = affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) - require.NoError(t, err) - if tc.affiliateRevShareAcctAddr != "" { - err := affiliatesKeeper.RegisterAffiliate(ctx, refereeAccAddr, tc.affiliateRevShareAcctAddr) - require.NoError(t, err) - } - if tc.unconditionalRevShareAcctAddr != "" { - err := affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) - require.NoError(t, err) - revShareKeeper.SetUnconditionalRevShareConfigParams(ctx, - revsharetypes.UnconditionalRevShareConfig{ - Configs: []revsharetypes.UnconditionalRevShareConfig_RecipientConfig{ - { - Address: tc.unconditionalRevShareAcctAddr, - SharePpm: defaultUnconditionalRevSharePpm, - }, - }, - }) - } - affiliateWhitelistMap, err := affiliatesKeeper.GetAffiliateWhitelistMap(ctx) - require.NoError(t, err) - revSharesForFill, err := revShareKeeper.GetAllRevShares(ctx, tc.fill, affiliateWhitelistMap) - require.NoError(t, err) - err = keeper.DistributeFees(ctx, tc.asset.Id, revSharesForFill, tc.fill) + err = keeper.DistributeFees(ctx, tc.asset.Id, tc.revShare, tc.fill) if tc.expectedErr != nil { require.ErrorIs(t, diff --git a/protocol/x/subaccounts/types/expected_keepers.go b/protocol/x/subaccounts/types/expected_keepers.go index 9d770273eb..a9e3f88f94 100644 --- a/protocol/x/subaccounts/types/expected_keepers.go +++ b/protocol/x/subaccounts/types/expected_keepers.go @@ -96,14 +96,3 @@ type BankKeeper interface { type BlocktimeKeeper interface { GetDowntimeInfoFor(ctx sdk.Context, duration time.Duration) blocktimetypes.AllDowntimeInfo_DowntimeInfo } - -type RevShareKeeper interface { - GetMarketMapperRevenueShareForMarket( - ctx sdk.Context, - marketId uint32, - ) ( - address sdk.AccAddress, - revenueSharePpm uint32, - err error, - ) -} From e4249ec6fad10554711a02a97c3261345d39fbeb Mon Sep 17 00:00:00 2001 From: Mohammed Affan Date: Mon, 23 Sep 2024 23:24:39 -0400 Subject: [PATCH 08/10] [OTE-788] Update revshare safety (#2284) --- protocol/app/app.go | 49 ++++---- protocol/testing/e2e/gov/feetiers_test.go | 8 +- protocol/testutil/keeper/assets.go | 4 +- protocol/testutil/keeper/clob.go | 32 +++--- protocol/testutil/keeper/listing.go | 30 ++--- protocol/testutil/keeper/perpetuals.go | 4 +- protocol/testutil/keeper/prices.go | 4 +- protocol/testutil/keeper/revshare.go | 7 +- protocol/testutil/keeper/rewards.go | 24 ++-- protocol/testutil/keeper/sending.go | 4 +- protocol/testutil/keeper/subaccounts.go | 5 +- protocol/x/affiliates/keeper/keeper.go | 6 +- protocol/x/affiliates/keeper/msg_server.go | 42 +------ .../x/affiliates/types/expected_keepers.go | 15 +-- protocol/x/feetiers/keeper/keeper.go | 40 ++++++- protocol/x/feetiers/keeper/keeper_test.go | 29 +++++ protocol/x/feetiers/keeper/params.go | 23 ++++ protocol/x/feetiers/types/errors.go | 5 + protocol/x/feetiers/types/expected_keepers.go | 24 +++- protocol/x/feetiers/types/types.go | 1 + protocol/x/revshare/keeper/keeper.go | 4 + .../msg_set_marketmapper_revenue_share.go | 19 ++-- ...sg_update_unconditional_revshare_config.go | 19 ++-- protocol/x/revshare/keeper/revshare.go | 41 ++++--- protocol/x/revshare/keeper/revshare_test.go | 105 ++++-------------- 25 files changed, 285 insertions(+), 259 deletions(-) diff --git a/protocol/app/app.go b/protocol/app/app.go index d45290bc17..d45a739b8e 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -949,26 +949,40 @@ func New( ) affiliatesModule := affiliatesmodule.NewAppModule(appCodec, app.AffiliatesKeeper) - app.RevShareKeeper = *revsharemodulekeeper.NewKeeper( + app.MarketMapKeeper = *marketmapmodulekeeper.NewKeeper( + runtime.NewKVStoreService(keys[marketmapmoduletypes.StoreKey]), appCodec, - keys[revsharemoduletypes.StoreKey], + authtypes.NewModuleAddress(govtypes.ModuleName), + ) + + marketmapModule := marketmapmodule.NewAppModule(appCodec, &app.MarketMapKeeper) + + app.FeeTiersKeeper = feetiersmodulekeeper.NewKeeper( + appCodec, + app.StatsKeeper, + app.AffiliatesKeeper, + keys[feetiersmoduletypes.StoreKey], + // set the governance and delaymsg module accounts as the authority for conducting upgrades []string{ lib.GovModuleAddress.String(), + delaymsgmoduletypes.ModuleAddress.String(), }, - app.AffiliatesKeeper, ) - revShareModule := revsharemodule.NewAppModule(appCodec, app.RevShareKeeper) + feeTiersModule := feetiersmodule.NewAppModule(appCodec, app.FeeTiersKeeper) - // Set the revshare keeper in the affiliates keeper. - app.AffiliatesKeeper.SetRevShareKeeper(app.RevShareKeeper) + app.AffiliatesKeeper.SetFeetiersKeeper(app.FeeTiersKeeper) - app.MarketMapKeeper = *marketmapmodulekeeper.NewKeeper( - runtime.NewKVStoreService(keys[marketmapmoduletypes.StoreKey]), + app.RevShareKeeper = *revsharemodulekeeper.NewKeeper( appCodec, - authtypes.NewModuleAddress(govtypes.ModuleName), + keys[revsharemoduletypes.StoreKey], + []string{ + lib.GovModuleAddress.String(), + }, + app.AffiliatesKeeper, + *app.FeeTiersKeeper, ) - - marketmapModule := marketmapmodule.NewAppModule(appCodec, &app.MarketMapKeeper) + revShareModule := revsharemodule.NewAppModule(appCodec, app.RevShareKeeper) + app.FeeTiersKeeper.SetRevShareKeeper(app.RevShareKeeper) app.PricesKeeper = *pricesmodulekeeper.NewKeeper( appCodec, @@ -1041,19 +1055,6 @@ func New( ) perpetualsModule := perpetualsmodule.NewAppModule(appCodec, app.PerpetualsKeeper) - app.FeeTiersKeeper = feetiersmodulekeeper.NewKeeper( - appCodec, - app.StatsKeeper, - app.AffiliatesKeeper, - keys[feetiersmoduletypes.StoreKey], - // set the governance and delaymsg module accounts as the authority for conducting upgrades - []string{ - lib.GovModuleAddress.String(), - delaymsgmoduletypes.ModuleAddress.String(), - }, - ) - feeTiersModule := feetiersmodule.NewAppModule(appCodec, app.FeeTiersKeeper) - app.VestKeeper = *vestmodulekeeper.NewKeeper( appCodec, keys[vestmoduletypes.StoreKey], diff --git a/protocol/testing/e2e/gov/feetiers_test.go b/protocol/testing/e2e/gov/feetiers_test.go index 8434897c93..9a5fd16909 100644 --- a/protocol/testing/e2e/gov/feetiers_test.go +++ b/protocol/testing/e2e/gov/feetiers_test.go @@ -20,16 +20,16 @@ func TestUpdateFeeTiersModuleParams(t *testing.T) { Tiers: []*feetierstypes.PerpetualFeeTier{ { Name: "test_tier_0", - MakerFeePpm: 1_000, - TakerFeePpm: 2_000, + MakerFeePpm: 11_000, + TakerFeePpm: 22_000, }, { Name: "test_tier_1", AbsoluteVolumeRequirement: 200_000, TotalVolumeShareRequirementPpm: 100_000, MakerVolumeShareRequirementPpm: 50_000, - MakerFeePpm: 11_000, - TakerFeePpm: 22_000, + MakerFeePpm: 1_000, + TakerFeePpm: 2_000, }, }, } diff --git a/protocol/testutil/keeper/assets.go b/protocol/testutil/keeper/assets.go index 1148db28f3..bdf43259cc 100644 --- a/protocol/testutil/keeper/assets.go +++ b/protocol/testutil/keeper/assets.go @@ -80,7 +80,9 @@ func AssetsKeepers( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, msgSenderEnabled) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) marketMapKeeper, _ := createMarketMapKeeper(stateStore, db, cdc) pricesKeeper, _, _, mockTimeProvider = createPricesKeeper( stateStore, diff --git a/protocol/testutil/keeper/clob.go b/protocol/testutil/keeper/clob.go index 0e544921df..eddbabd9bf 100644 --- a/protocol/testutil/keeper/clob.go +++ b/protocol/testutil/keeper/clob.go @@ -109,7 +109,23 @@ func NewClobKeepersTestContextWithUninitializedMemStore( ) ks.AffiliatesKeeper, _ = createAffiliatesKeeper(stateStore, db, cdc, ks.StatsKeeper, indexerEventsTransientStoreKey, true) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, ks.AffiliatesKeeper) + ks.VaultKeeper, _ = createVaultKeeper( + stateStore, + db, + cdc, + indexerEventsTransientStoreKey, + ) + ks.FeeTiersKeeper, _ = createFeeTiersKeeper( + stateStore, + ks.StatsKeeper, + ks.VaultKeeper, + ks.AffiliatesKeeper, + db, + cdc, + ) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, ks.AffiliatesKeeper, ks.FeeTiersKeeper) + ks.FeeTiersKeeper.SetRevShareKeeper(revShareKeeper) + ks.AffiliatesKeeper.SetFeetiersKeeper(ks.FeeTiersKeeper) ks.MarketMapKeeper, _ = createMarketMapKeeper(stateStore, db, cdc) ks.PricesKeeper, _, _, mockTimeProvider = createPricesKeeper( stateStore, @@ -138,20 +154,6 @@ func NewClobKeepersTestContextWithUninitializedMemStore( true, ) ks.BlockTimeKeeper, _ = createBlockTimeKeeper(stateStore, db, cdc) - ks.VaultKeeper, _ = createVaultKeeper( - stateStore, - db, - cdc, - indexerEventsTransientStoreKey, - ) - ks.FeeTiersKeeper, _ = createFeeTiersKeeper( - stateStore, - ks.StatsKeeper, - ks.VaultKeeper, - ks.AffiliatesKeeper, - db, - cdc, - ) ks.RewardsKeeper, _ = createRewardsKeeper( stateStore, ks.AssetsKeeper, diff --git a/protocol/testutil/keeper/listing.go b/protocol/testutil/keeper/listing.go index 7b34551a2a..39e5b80cac 100644 --- a/protocol/testutil/keeper/listing.go +++ b/protocol/testutil/keeper/listing.go @@ -72,7 +72,21 @@ func ListingKeepers( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + vaultKeeper, _ := createVaultKeeper( + stateStore, + db, + cdc, + transientStoreKey, + ) + feeTiersKeeper, _ := createFeeTiersKeeper( + stateStore, + statsKeeper, + vaultKeeper, + affiliatesKeeper, + db, + cdc, + ) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feeTiersKeeper) marketMapKeeper, _ = createMarketMapKeeper(stateStore, db, cdc) pricesKeeper, _, _, mockTimeProvider = createPricesKeeper( stateStore, @@ -102,20 +116,6 @@ func ListingKeepers( ) blockTimeKeeper, _ := createBlockTimeKeeper(stateStore, db, cdc) - vaultKeeper, _ := createVaultKeeper( - stateStore, - db, - cdc, - transientStoreKey, - ) - feeTiersKeeper, _ := createFeeTiersKeeper( - stateStore, - statsKeeper, - vaultKeeper, - affiliatesKeeper, - db, - cdc, - ) rewardsKeeper, _ := createRewardsKeeper( stateStore, assetsKeeper, diff --git a/protocol/testutil/keeper/perpetuals.go b/protocol/testutil/keeper/perpetuals.go index 62d333c824..0805ea94fc 100644 --- a/protocol/testutil/keeper/perpetuals.go +++ b/protocol/testutil/keeper/perpetuals.go @@ -89,7 +89,9 @@ func PerpetualsKeepersWithClobHelpers( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) pc.MarketMapKeeper, _ = createMarketMapKeeper(stateStore, db, cdc) pc.PricesKeeper, _, pc.IndexPriceCache, pc.MockTimeProvider = createPricesKeeper( stateStore, diff --git a/protocol/testutil/keeper/prices.go b/protocol/testutil/keeper/prices.go index 5419ecba32..ef6c53a5fb 100644 --- a/protocol/testutil/keeper/prices.go +++ b/protocol/testutil/keeper/prices.go @@ -70,7 +70,9 @@ func PricesKeepers(t testing.TB) ( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ = createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) + revShareKeeper, _, _ = createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) marketMapKeeper, _ = createMarketMapKeeper(stateStore, db, cdc) // Define necessary keepers here for unit tests keeper, storeKey, indexPriceCache, mockTimeProvider = diff --git a/protocol/testutil/keeper/revshare.go b/protocol/testutil/keeper/revshare.go index c7d378f917..ea3b786d5d 100644 --- a/protocol/testutil/keeper/revshare.go +++ b/protocol/testutil/keeper/revshare.go @@ -8,6 +8,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/dydxprotocol/v4-chain/protocol/lib" affiliateskeeper "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/keeper" + feetierskeeper "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/keeper" "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" storetypes "cosmossdk.io/store/types" @@ -54,8 +55,10 @@ func RevShareKeepers(t testing.TB) ( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) keeper, storeKey, mockTimeProvider = - createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) return []GenesisInitializer{keeper} }, @@ -69,6 +72,7 @@ func createRevShareKeeper( db *dbm.MemDB, cdc *codec.ProtoCodec, affiliatesKeeper *affiliateskeeper.Keeper, + feetiersKeeper *feetierskeeper.Keeper, ) ( *keeper.Keeper, storetypes.StoreKey, @@ -83,6 +87,7 @@ func createRevShareKeeper( lib.GovModuleAddress.String(), }, *affiliatesKeeper, + *feetiersKeeper, ) return k, storeKey, mockTimeProvider diff --git a/protocol/testutil/keeper/rewards.go b/protocol/testutil/keeper/rewards.go index ebb3226de1..d6c1aaf620 100644 --- a/protocol/testutil/keeper/rewards.go +++ b/protocol/testutil/keeper/rewards.go @@ -66,18 +66,6 @@ func RewardsKeepers( stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) - marketMapKeeper, _ := createMarketMapKeeper(stateStore, db, cdc) - pricesKeeper, _, _, _ = createPricesKeeper(stateStore, db, cdc, transientStoreKey, revShareKeeper, marketMapKeeper) - // Mock time provider response for market creation. - assetsKeeper, _ = createAssetsKeeper( - stateStore, - db, - cdc, - pricesKeeper, - transientStoreKey, - true, - ) vaultKeeper, _ := createVaultKeeper( stateStore, db, @@ -92,6 +80,18 @@ func RewardsKeepers( db, cdc, ) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) + marketMapKeeper, _ := createMarketMapKeeper(stateStore, db, cdc) + pricesKeeper, _, _, _ = createPricesKeeper(stateStore, db, cdc, transientStoreKey, revShareKeeper, marketMapKeeper) + // Mock time provider response for market creation. + assetsKeeper, _ = createAssetsKeeper( + stateStore, + db, + cdc, + pricesKeeper, + transientStoreKey, + true, + ) rewardsKeeper, storeKey = createRewardsKeeper( stateStore, assetsKeeper, diff --git a/protocol/testutil/keeper/sending.go b/protocol/testutil/keeper/sending.go index 7adb413cc2..7a0dd77d58 100644 --- a/protocol/testutil/keeper/sending.go +++ b/protocol/testutil/keeper/sending.go @@ -78,7 +78,9 @@ func SendingKeepersWithSubaccountsKeeper(t testing.TB, saKeeper types.Subaccount stakingKeeper, ) affiliatesKeeper, _ := createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) + revShareKeeper, _, _ := createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) marketMapKeeper, _ := createMarketMapKeeper(stateStore, db, cdc) ks.PricesKeeper, _, _, mockTimeProvider = createPricesKeeper( stateStore, diff --git a/protocol/testutil/keeper/subaccounts.go b/protocol/testutil/keeper/subaccounts.go index 127cdf60ac..a0c14b3fc0 100644 --- a/protocol/testutil/keeper/subaccounts.go +++ b/protocol/testutil/keeper/subaccounts.go @@ -77,8 +77,9 @@ func SubaccountsKeepers(t testing.TB, msgSenderEnabled bool) ( stakingKeeper, ) affiliatesKeeper, _ = createAffiliatesKeeper(stateStore, db, cdc, statsKeeper, transientStoreKey, true) - revShareKeeper, _, _ = createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper) - affiliatesKeeper.SetRevShareKeeper(revShareKeeper) + vaultKeeper, _ := createVaultKeeper(stateStore, db, cdc, transientStoreKey) + feetiersKeeper, _ := createFeeTiersKeeper(stateStore, statsKeeper, vaultKeeper, affiliatesKeeper, db, cdc) + revShareKeeper, _, _ = createRevShareKeeper(stateStore, db, cdc, affiliatesKeeper, feetiersKeeper) marketMapKeeper, _ := createMarketMapKeeper(stateStore, db, cdc) pricesKeeper, _, _, mockTimeProvider = createPricesKeeper( stateStore, diff --git a/protocol/x/affiliates/keeper/keeper.go b/protocol/x/affiliates/keeper/keeper.go index e35f18a5e9..f942e46418 100644 --- a/protocol/x/affiliates/keeper/keeper.go +++ b/protocol/x/affiliates/keeper/keeper.go @@ -23,7 +23,7 @@ type ( storeKey storetypes.StoreKey authorities map[string]struct{} statsKeeper types.StatsKeeper - revShareKeeper types.RevShareKeeper + feetiersKeeper types.FeetiersKeeper indexerEventManager indexer_manager.IndexerEventManager } ) @@ -278,8 +278,8 @@ func (k Keeper) UpdateAffiliateTiers(ctx sdk.Context, affiliateTiers types.Affil return nil } -func (k *Keeper) SetRevShareKeeper(revShareKeeper types.RevShareKeeper) { - k.revShareKeeper = revShareKeeper +func (k *Keeper) SetFeetiersKeeper(feetiersKeeper types.FeetiersKeeper) { + k.feetiersKeeper = feetiersKeeper } func (k Keeper) GetIndexerEventManager() indexer_manager.IndexerEventManager { diff --git a/protocol/x/affiliates/keeper/msg_server.go b/protocol/x/affiliates/keeper/msg_server.go index 49be6ed542..f1c535c6e5 100644 --- a/protocol/x/affiliates/keeper/msg_server.go +++ b/protocol/x/affiliates/keeper/msg_server.go @@ -4,7 +4,6 @@ import ( "context" "errors" - errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" ) @@ -38,25 +37,8 @@ func (k msgServer) UpdateAffiliateTiers(ctx context.Context, } sdkCtx := sdk.UnwrapSDKContext(ctx) - unconditionalRevShareConfig, err := k.revShareKeeper.GetUnconditionalRevShareConfigParams(sdkCtx) - if err != nil { - return nil, err - } - marketMapperRevShareParams := k.revShareKeeper.GetMarketMapperRevenueShareParams(sdkCtx) - affiliateWhitelist, err := k.GetAffiliateWhitelist(sdkCtx) - if err != nil { - return nil, err - } - - if !k.revShareKeeper.ValidateRevShareSafety(msg.Tiers, - unconditionalRevShareConfig, marketMapperRevShareParams, affiliateWhitelist) { - return nil, errorsmod.Wrapf( - types.ErrRevShareSafetyViolation, - "rev share safety violation", - ) - } - err = k.Keeper.UpdateAffiliateTiers(sdkCtx, msg.Tiers) + err := k.Keeper.UpdateAffiliateTiers(sdkCtx, msg.Tiers) if err != nil { return nil, err } @@ -70,27 +52,7 @@ func (k msgServer) UpdateAffiliateWhitelist(ctx context.Context, return nil, errors.New("invalid authority") } - sdkCtx := sdk.UnwrapSDKContext(ctx) - unconditionalRevShareConfig, err := k.revShareKeeper.GetUnconditionalRevShareConfigParams(sdkCtx) - if err != nil { - return nil, err - } - marketMapperRevShareParams := k.revShareKeeper.GetMarketMapperRevenueShareParams(sdkCtx) - - affiliateTiers, err := k.Keeper.GetAllAffiliateTiers(sdkCtx) - if err != nil { - return nil, err - } - - if !k.revShareKeeper.ValidateRevShareSafety(affiliateTiers, - unconditionalRevShareConfig, marketMapperRevShareParams, msg.Whitelist) { - return nil, errorsmod.Wrapf( - types.ErrRevShareSafetyViolation, - "rev share safety violation", - ) - } - - err = k.Keeper.SetAffiliateWhitelist(sdk.UnwrapSDKContext(ctx), msg.Whitelist) + err := k.Keeper.SetAffiliateWhitelist(sdk.UnwrapSDKContext(ctx), msg.Whitelist) if err != nil { return nil, err } diff --git a/protocol/x/affiliates/types/expected_keepers.go b/protocol/x/affiliates/types/expected_keepers.go index eca412e1de..b92c4d304a 100644 --- a/protocol/x/affiliates/types/expected_keepers.go +++ b/protocol/x/affiliates/types/expected_keepers.go @@ -4,7 +4,6 @@ import ( "math/big" sdk "github.com/cosmos/cosmos-sdk/types" - revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" stattypes "github.com/dydxprotocol/v4-chain/protocol/x/stats/types" ) @@ -13,15 +12,7 @@ type StatsKeeper interface { GetBlockStats(ctx sdk.Context) *stattypes.BlockStats } -type RevShareKeeper interface { - GetUnconditionalRevShareConfigParams(ctx sdk.Context) (revsharetypes.UnconditionalRevShareConfig, error) - GetMarketMapperRevenueShareParams( - ctx sdk.Context, - ) revsharetypes.MarketMapperRevenueShareParams - ValidateRevShareSafety( - affiliateTiers AffiliateTiers, - unconditionalRevShareConfig revsharetypes.UnconditionalRevShareConfig, - marketMapperRevShareParams revsharetypes.MarketMapperRevenueShareParams, - affiliateWhitelist AffiliateWhitelist, - ) bool +type FeetiersKeeper interface { + GetAffiliateRefereeLowestTakerFee(ctx sdk.Context) int32 + GetLowestMakerFee(ctx sdk.Context) int32 } diff --git a/protocol/x/feetiers/keeper/keeper.go b/protocol/x/feetiers/keeper/keeper.go index a3d403aeb3..98ce7d3086 100644 --- a/protocol/x/feetiers/keeper/keeper.go +++ b/protocol/x/feetiers/keeper/keeper.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/types" + revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" ) type ( @@ -21,6 +22,7 @@ type ( storeKey storetypes.StoreKey authorities map[string]struct{} affiliatesKeeper types.AffiliatesKeeper + revShareKeeper types.RevShareKeeper } ) @@ -122,12 +124,46 @@ func (k Keeper) GetPerpetualFeePpm(ctx sdk.Context, address string, isTaker bool func (k Keeper) GetLowestMakerFee(ctx sdk.Context) int32 { feeParams := k.GetPerpetualFeeParams(ctx) + return GetLowestMakerFeeFromTiers(feeParams.Tiers) +} + +func (k Keeper) GetAffiliateRefereeLowestTakerFee(ctx sdk.Context) int32 { + feeParams := k.GetPerpetualFeeParams(ctx) + + return GetAffiliateRefereeLowestTakerFeeFromTiers(feeParams.Tiers) +} + +func (k *Keeper) SetRevShareKeeper(revShareKeeper types.RevShareKeeper) { + k.revShareKeeper = revShareKeeper +} + +func GetLowestMakerFeeFromTiers(tiers []*types.PerpetualFeeTier) int32 { lowestMakerFee := int32(math.MaxInt32) - for _, tier := range feeParams.Tiers { + for _, tier := range tiers { if tier.MakerFeePpm < lowestMakerFee { lowestMakerFee = tier.MakerFeePpm } } - return lowestMakerFee } + +// GetAffiliateRefereeLowestTakerFeeFromTiers returns the minimum of +// - the taker fee of the tier that has the max absolute volume requirement +// - the taker fee of the referee starting fee tier +func GetAffiliateRefereeLowestTakerFeeFromTiers(tiers []*types.PerpetualFeeTier) int32 { + takerFeePpm := int32(math.MaxInt32) + for _, tier := range tiers { + // assumes tiers are ordered by absolute volume requirement + if tier.AbsoluteVolumeRequirement < revsharetypes.MaxReferee30dVolumeForAffiliateShareQuantums { + takerFeePpm = tier.TakerFeePpm + } else { + break + } + } + + if uint32(len(tiers)) > types.RefereeStartingFeeTier { + return min(takerFeePpm, tiers[types.RefereeStartingFeeTier].TakerFeePpm) + } + + return takerFeePpm +} diff --git a/protocol/x/feetiers/keeper/keeper_test.go b/protocol/x/feetiers/keeper/keeper_test.go index 3716c2d835..56c94f7237 100644 --- a/protocol/x/feetiers/keeper/keeper_test.go +++ b/protocol/x/feetiers/keeper/keeper_test.go @@ -8,6 +8,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" affiliateskeeper "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/keeper" affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" + feetierskeeper "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/keeper" "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/types" statskeeper "github.com/dydxprotocol/v4-chain/protocol/x/stats/keeper" stattypes "github.com/dydxprotocol/v4-chain/protocol/x/stats/types" @@ -352,3 +353,31 @@ func TestGetMaxMakerRebate(t *testing.T) { }) } } + +func TestGetAffiliateRefereeLowestTakerFee(t *testing.T) { + tests := map[string]struct { + expectedLowestTakerFee int32 + feeTiers types.PerpetualFeeParams + }{ + "tiers are ordered by absolute volume requirement": { + feeTiers: types.StandardParams(), + expectedLowestTakerFee: 350, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + tApp := testapp.NewTestAppBuilder(t).Build() + ctx := tApp.InitChain() + k := tApp.App.FeeTiersKeeper + err := k.SetPerpetualFeeParams( + ctx, + tc.feeTiers, + ) + require.NoError(t, err) + + feeTiers := k.GetPerpetualFeeParams(ctx).Tiers + require.Equal(t, tc.expectedLowestTakerFee, feetierskeeper.GetAffiliateRefereeLowestTakerFeeFromTiers(feeTiers)) + }) + } +} diff --git a/protocol/x/feetiers/keeper/params.go b/protocol/x/feetiers/keeper/params.go index 2c1ebbe5f8..5ec72b3b56 100644 --- a/protocol/x/feetiers/keeper/params.go +++ b/protocol/x/feetiers/keeper/params.go @@ -1,6 +1,7 @@ package keeper import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/types" ) @@ -27,6 +28,28 @@ func (k Keeper) SetPerpetualFeeParams( return err } + lowestMakerFee := GetLowestMakerFeeFromTiers(params.Tiers) + lowestTakerFee := GetAffiliateRefereeLowestTakerFeeFromTiers(params.Tiers) + + unconditionalRevShareConfig, err := k.revShareKeeper.GetUnconditionalRevShareConfigParams(ctx) + if err != nil { + return err + } + + marketMapperRevShareParams := k.revShareKeeper.GetMarketMapperRevenueShareParams(ctx) + if err != nil { + return err + } + + valid := k.revShareKeeper.ValidateRevShareSafety(ctx, unconditionalRevShareConfig, + marketMapperRevShareParams, lowestTakerFee, lowestMakerFee) + if !valid { + return errorsmod.Wrapf( + types.ErrRevShareSafetyViolation, + "rev share safety violation", + ) + } + store := ctx.KVStore(k.storeKey) b := k.cdc.MustMarshal(¶ms) store.Set([]byte(types.PerpetualFeeParamsKey), b) diff --git a/protocol/x/feetiers/types/errors.go b/protocol/x/feetiers/types/errors.go index 3342180706..fd15a402d8 100644 --- a/protocol/x/feetiers/types/errors.go +++ b/protocol/x/feetiers/types/errors.go @@ -30,4 +30,9 @@ var ( 404, "Authority is invalid", ) + ErrRevShareSafetyViolation = errorsmod.Register( + ModuleName, + 405, + "Rev share safety violation", + ) ) diff --git a/protocol/x/feetiers/types/expected_keepers.go b/protocol/x/feetiers/types/expected_keepers.go index 104db0eb61..f9a17782b3 100644 --- a/protocol/x/feetiers/types/expected_keepers.go +++ b/protocol/x/feetiers/types/expected_keepers.go @@ -2,13 +2,15 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/dydxprotocol/v4-chain/protocol/x/stats/types" + affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" + revsharetypes "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" + statstypes "github.com/dydxprotocol/v4-chain/protocol/x/stats/types" ) // StatsKeeper defines the expected stats keeper type StatsKeeper interface { - GetUserStats(ctx sdk.Context, address string) *types.UserStats - GetGlobalStats(ctx sdk.Context) *types.GlobalStats + GetUserStats(ctx sdk.Context, address string) *statstypes.UserStats + GetGlobalStats(ctx sdk.Context) *statstypes.GlobalStats } // VaultKeeper defines the expected vault keeper. @@ -19,4 +21,20 @@ type VaultKeeper interface { // AffiliatesKeeper defines the expected affiliates keeper. type AffiliatesKeeper interface { GetReferredBy(ctx sdk.Context, referee string) (string, bool) + GetAllAffiliateTiers(ctx sdk.Context) (affiliatetypes.AffiliateTiers, error) +} + +// RevShareKeeper defines the expected revshare keeper. +type RevShareKeeper interface { + GetUnconditionalRevShareConfigParams(ctx sdk.Context) (revsharetypes.UnconditionalRevShareConfig, error) + GetMarketMapperRevenueShareParams( + ctx sdk.Context, + ) revsharetypes.MarketMapperRevenueShareParams + ValidateRevShareSafety( + ctx sdk.Context, + unconditionalRevShareConfig revsharetypes.UnconditionalRevShareConfig, + marketMapperRevShareParams revsharetypes.MarketMapperRevenueShareParams, + lowestTakerFee int32, + lowestMakerFee int32, + ) bool } diff --git a/protocol/x/feetiers/types/types.go b/protocol/x/feetiers/types/types.go index 783398c09d..348d5f478d 100644 --- a/protocol/x/feetiers/types/types.go +++ b/protocol/x/feetiers/types/types.go @@ -6,6 +6,7 @@ import ( type FeeTiersKeeper interface { GetLowestMakerFee(ctx sdk.Context) int32 + GetAffiliateRefereeLowestTakerFee(ctx sdk.Context) int32 GetPerpetualFeePpm(ctx sdk.Context, address string, isTaker bool) int32 GetPerpetualFeeParams( ctx sdk.Context, diff --git a/protocol/x/revshare/keeper/keeper.go b/protocol/x/revshare/keeper/keeper.go index 598ccde053..11dac305c2 100644 --- a/protocol/x/revshare/keeper/keeper.go +++ b/protocol/x/revshare/keeper/keeper.go @@ -9,6 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/lib" affiliateskeeper "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/keeper" + feetierskeeper "github.com/dydxprotocol/v4-chain/protocol/x/feetiers/keeper" "github.com/dydxprotocol/v4-chain/protocol/x/revshare/types" ) @@ -18,6 +19,7 @@ type ( storeKey storetypes.StoreKey authorities map[string]struct{} affiliatesKeeper affiliateskeeper.Keeper + feetiersKeeper feetierskeeper.Keeper } ) @@ -26,12 +28,14 @@ func NewKeeper( storeKey storetypes.StoreKey, authorities []string, affiliatesKeeper affiliateskeeper.Keeper, + feetiersKeeper feetierskeeper.Keeper, ) *Keeper { return &Keeper{ cdc: cdc, storeKey: storeKey, authorities: lib.UniqueSliceToSet(authorities), affiliatesKeeper: affiliatesKeeper, + feetiersKeeper: feetiersKeeper, } } diff --git a/protocol/x/revshare/keeper/msg_set_marketmapper_revenue_share.go b/protocol/x/revshare/keeper/msg_set_marketmapper_revenue_share.go index 72d139b62a..4a7bf5eb90 100644 --- a/protocol/x/revshare/keeper/msg_set_marketmapper_revenue_share.go +++ b/protocol/x/revshare/keeper/msg_set_marketmapper_revenue_share.go @@ -29,16 +29,17 @@ func (k msgServer) SetMarketMapperRevenueShare( if err != nil { return nil, err } - affiliateTiers, err := k.affiliatesKeeper.GetAllAffiliateTiers(ctx) - if err != nil { - return nil, err - } - affiliateWhitelist, err := k.affiliatesKeeper.GetAffiliateWhitelist(ctx) - if err != nil { - return nil, err - } - if !k.ValidateRevShareSafety(affiliateTiers, unconditionalRevShareConfig, msg.Params, affiliateWhitelist) { + lowestTakerFeePpm := k.feetiersKeeper.GetAffiliateRefereeLowestTakerFee(ctx) + lowestMakerFeePpm := k.feetiersKeeper.GetLowestMakerFee(ctx) + + if !k.ValidateRevShareSafety( + ctx, + unconditionalRevShareConfig, + msg.Params, + lowestTakerFeePpm, + lowestMakerFeePpm, + ) { return nil, errorsmod.Wrapf( types.ErrRevShareSafetyViolation, "rev share safety violation", diff --git a/protocol/x/revshare/keeper/msg_update_unconditional_revshare_config.go b/protocol/x/revshare/keeper/msg_update_unconditional_revshare_config.go index 538126352c..52383a7c85 100644 --- a/protocol/x/revshare/keeper/msg_update_unconditional_revshare_config.go +++ b/protocol/x/revshare/keeper/msg_update_unconditional_revshare_config.go @@ -29,16 +29,17 @@ func (k msgServer) UpdateUnconditionalRevShareConfig( return nil, err } - affiliateTiers, err := k.affiliatesKeeper.GetAllAffiliateTiers(ctx) - if err != nil { - return nil, err - } - affiliateWhitelist, err := k.affiliatesKeeper.GetAffiliateWhitelist(ctx) - if err != nil { - return nil, err - } + lowestTakerFee := k.feetiersKeeper.GetAffiliateRefereeLowestTakerFee(ctx) + lowestMakerFee := k.feetiersKeeper.GetLowestMakerFee(ctx) + marketMapperRevShareParams := k.GetMarketMapperRevenueShareParams(ctx) - if !k.ValidateRevShareSafety(affiliateTiers, msg.Config, marketMapperRevShareParams, affiliateWhitelist) { + if !k.ValidateRevShareSafety( + ctx, + msg.Config, + marketMapperRevShareParams, + lowestTakerFee, + lowestMakerFee, + ) { return nil, errorsmod.Wrapf( types.ErrRevShareSafetyViolation, "rev share safety violation", diff --git a/protocol/x/revshare/keeper/revshare.go b/protocol/x/revshare/keeper/revshare.go index 74ea0c0158..a842083791 100644 --- a/protocol/x/revshare/keeper/revshare.go +++ b/protocol/x/revshare/keeper/revshare.go @@ -122,34 +122,39 @@ func (k Keeper) SetUnconditionalRevShareConfigParams(ctx sdk.Context, config typ store.Set([]byte(types.UnconditionalRevShareConfigKey), unconditionalRevShareConfigBytes) } -// ValidateRevShareSafety roughly checks if the total rev share is valid using the formula below -// highest_affiliate_taker_share + sum(unconditional_rev_shares) + market_mapper_rev_share < 100% -// Note: this is just an estimate as affiliate rev share is based on taker fees, while -// the rest of the rev share is based on net fees. -// TODO(OTE-788): Revisit this formula to ensure accuracy. +// Check two conditions to ensure rev shares are safe. +// 1. totalUnconditionalRevSharePpm + totalMarketMapperRevSharePpm < 100% +// 2. lowest_taker_fee + lowest_maker_fee >= Highest_affiliate_rev_share * lowest_taker_fee func (k Keeper) ValidateRevShareSafety( - affiliateTiers affiliatetypes.AffiliateTiers, + ctx sdk.Context, unconditionalRevShareConfig types.UnconditionalRevShareConfig, marketMapperRevShareParams types.MarketMapperRevenueShareParams, - affiliateWhitelist affiliatetypes.AffiliateWhitelist, + lowestTakerFeePpm int32, + lowestMakerFeePpm int32, ) bool { - highestAffilliateTierRevSharePpm := uint32(0) - if len(affiliateTiers.Tiers) > 0 { - highestAffilliateTierRevSharePpm = affiliateTiers.Tiers[len(affiliateTiers.Tiers)-1].TakerFeeSharePpm - } - for _, tier := range affiliateWhitelist.Tiers { - if tier.TakerFeeSharePpm > highestAffilliateTierRevSharePpm { - highestAffilliateTierRevSharePpm = tier.TakerFeeSharePpm - } - } totalUnconditionalRevSharePpm := uint32(0) for _, recipientConfig := range unconditionalRevShareConfig.Configs { totalUnconditionalRevSharePpm += recipientConfig.SharePpm } totalMarketMapperRevSharePpm := marketMapperRevShareParams.RevenueSharePpm - totalRevSharePpm := totalUnconditionalRevSharePpm + totalMarketMapperRevSharePpm + highestAffilliateTierRevSharePpm - return totalRevSharePpm < lib.OneMillion + // return false if totalUnconditionalRevSharePpm + totalMarketMapperRevSharePpm >= 100% + if totalUnconditionalRevSharePpm+totalMarketMapperRevSharePpm >= lib.OneMillion { + return false + } + + bigNetFee := new(big.Int).SetUint64( + // Casting is safe since both variables are int32. + uint64(lowestTakerFeePpm) + uint64(lowestMakerFeePpm), + ) + + bigLowestTakerFeePpmMulRevShareRateCap := lib.BigMulPpm( + lib.BigI(lowestTakerFeePpm), + lib.BigU(affiliatetypes.AffiliatesRevSharePpmCap), + true, + ) + // TODO(OTE-826): Update ValidateRevshareSafety formula and fix tests + return bigNetFee.Cmp(bigLowestTakerFeePpmMulRevShareRateCap) >= 0 } func (k Keeper) GetAllRevShares( diff --git a/protocol/x/revshare/keeper/revshare_test.go b/protocol/x/revshare/keeper/revshare_test.go index 488a908679..23f2c2422f 100644 --- a/protocol/x/revshare/keeper/revshare_test.go +++ b/protocol/x/revshare/keeper/revshare_test.go @@ -175,14 +175,13 @@ func TestGetMarketMapperRevenueShareForMarket(t *testing.T) { func TestValidateRevShareSafety(t *testing.T) { tests := map[string]struct { - affiliateTiers affiliatetypes.AffiliateTiers revShareConfig types.UnconditionalRevShareConfig marketMapperRevShareParams types.MarketMapperRevenueShareParams - affiliateWhitelist affiliatetypes.AffiliateWhitelist + lowestTakerFee int32 + lowestMakerFee int32 expectedValid bool }{ "valid rev share config": { - affiliateTiers: affiliatetypes.DefaultAffiliateTiers, revShareConfig: types.UnconditionalRevShareConfig{ Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ { @@ -196,113 +195,47 @@ func TestValidateRevShareSafety(t *testing.T) { RevenueSharePpm: 100_000, // 10% ValidDays: 0, }, - affiliateWhitelist: affiliatetypes.AffiliateWhitelist{ - Tiers: []affiliatetypes.AffiliateWhitelist_Tier{ - { - Addresses: []string{constants.AliceAccAddress.String()}, - TakerFeeSharePpm: 100_000, // 10% - }, - }, - }, - expectedValid: true, - }, - "invalid rev share config - sum of shares > 100%": { - affiliateTiers: affiliatetypes.DefaultAffiliateTiers, - revShareConfig: types.UnconditionalRevShareConfig{ - Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ - { - Address: constants.AliceAccAddress.String(), - SharePpm: 100_000, // 10% - }, - { - Address: constants.BobAccAddress.String(), - SharePpm: 810_000, // 81% - }, - }, - }, - marketMapperRevShareParams: types.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% - ValidDays: 0, - }, - affiliateWhitelist: affiliatetypes.AffiliateWhitelist{ - Tiers: []affiliatetypes.AffiliateWhitelist_Tier{}, - }, - expectedValid: false, + lowestTakerFee: 350, + lowestMakerFee: -110, + expectedValid: true, }, - "invalid rev share config - sum of shares + highest tier share > 100%": { - affiliateTiers: affiliatetypes.AffiliateTiers{ - Tiers: []affiliatetypes.AffiliateTiers_Tier{ - { - ReqReferredVolumeQuoteQuantums: 0, - ReqStakedWholeCoins: 0, - TakerFeeSharePpm: 50_000, // 5% - }, - { - ReqReferredVolumeQuoteQuantums: 1_000_000_000_000, // 1 million USDC - ReqStakedWholeCoins: 200, // 200 whole coins - TakerFeeSharePpm: 800_000, // 80% - }, - }, - }, + "rev share safety violation: unconditional + marketmapper > 100%": { revShareConfig: types.UnconditionalRevShareConfig{ Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ { Address: constants.AliceAccAddress.String(), - SharePpm: 100_000, // 10% - }, - { - Address: constants.BobAccAddress.String(), - SharePpm: 100_000, // 10% + SharePpm: 600_000, // 60% }, }, }, marketMapperRevShareParams: types.MarketMapperRevenueShareParams{ Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 100_000, // 10% + RevenueSharePpm: 500_000, // 50% ValidDays: 0, }, - affiliateWhitelist: affiliatetypes.AffiliateWhitelist{}, - expectedValid: false, + lowestTakerFee: 350, + lowestMakerFee: -110, + expectedValid: false, }, - "invalid rev share config - very high whitelist tier share exceeding 100%": { - affiliateTiers: affiliatetypes.DefaultAffiliateTiers, - revShareConfig: types.UnconditionalRevShareConfig{ - Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ - { - Address: constants.AliceAccAddress.String(), - SharePpm: 200_000, // 20% - }, - }, - }, - marketMapperRevShareParams: types.MarketMapperRevenueShareParams{ - Address: constants.AliceAccAddress.String(), - RevenueSharePpm: 200_000, // 20% - ValidDays: 0, - }, - affiliateWhitelist: affiliatetypes.AffiliateWhitelist{ - Tiers: []affiliatetypes.AffiliateWhitelist_Tier{ - { - Addresses: []string{constants.AliceAccAddress.String()}, - TakerFeeSharePpm: 700_000, // 70% - }, - }, - }, - expectedValid: false, + "rev share safety violation: affiliate and fees": { + lowestTakerFee: 350, + lowestMakerFee: -220, + expectedValid: false, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { tApp := testapp.NewTestAppBuilder(t).Build() - _ = tApp.InitChain() + ctx := tApp.InitChain() k := tApp.App.RevShareKeeper valid := k.ValidateRevShareSafety( - tc.affiliateTiers, + ctx, tc.revShareConfig, tc.marketMapperRevShareParams, - tc.affiliateWhitelist, + tc.lowestTakerFee, + tc.lowestMakerFee, ) require.Equal(t, tc.expectedValid, valid) }) From 3202ca406ca03e087c032fed04bdd1a12be90deb Mon Sep 17 00:00:00 2001 From: jayy04 <103467857+jayy04@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:53:58 -0400 Subject: [PATCH 09/10] [CT-1197] add query methods for smart account (#2313) --- protocol/lib/metrics/metric_keys.go | 3 + .../x/accountplus/keeper/authenticators.go | 126 ++++++++++++++++++ protocol/x/accountplus/keeper/keeper_test.go | 30 +++++ protocol/x/accountplus/keeper/query.go | 69 ++++++++++ protocol/x/accountplus/types/codec.go | 5 + protocol/x/accountplus/types/errors.go | 5 + 6 files changed, 238 insertions(+) create mode 100644 protocol/x/accountplus/keeper/query.go diff --git a/protocol/lib/metrics/metric_keys.go b/protocol/lib/metrics/metric_keys.go index c7c42b4c44..9146cf1ff7 100644 --- a/protocol/lib/metrics/metric_keys.go +++ b/protocol/lib/metrics/metric_keys.go @@ -89,4 +89,7 @@ const ( EndBlocker = "end_blocker" EndBlockerLag = "end_blocker_lag" + + // Account plus + MissingRegisteredAuthenticator = "missing_registered_authenticator" ) diff --git a/protocol/x/accountplus/keeper/authenticators.go b/protocol/x/accountplus/keeper/authenticators.go index 4d604206c1..69c7599f57 100644 --- a/protocol/x/accountplus/keeper/authenticators.go +++ b/protocol/x/accountplus/keeper/authenticators.go @@ -6,8 +6,13 @@ import ( "cosmossdk.io/errors" "cosmossdk.io/store/prefix" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" gogotypes "github.com/cosmos/gogoproto/types" + "github.com/dydxprotocol/v4-chain/protocol/lib/metrics" + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator" "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" ) @@ -106,3 +111,124 @@ func (k Keeper) SetNextAuthenticatorId(ctx sdk.Context, authenticatorId uint64) store := ctx.KVStore(k.storeKey) store.Set([]byte(types.AuthenticatorIdKeyPrefix), b) } + +// GetSelectedAuthenticatorData gets a single authenticator for the account from the store. +func (k Keeper) GetSelectedAuthenticatorData( + ctx sdk.Context, + account sdk.AccAddress, + selectedAuthenticator uint64, +) (*types.AccountAuthenticator, error) { + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.AuthenticatorKeyPrefix), + ) + bz := store.Get(types.KeyAccountId(account, selectedAuthenticator)) + if bz == nil { + return &types.AccountAuthenticator{}, errors.Wrap( + types.ErrAuthenticatorNotFound, + fmt.Sprintf("authenticator %d not found for account %s", selectedAuthenticator, account), + ) + } + authenticatorFromStore, err := k.unmarshalAccountAuthenticator(bz) + if err != nil { + return &types.AccountAuthenticator{}, err + } + + return authenticatorFromStore, nil +} + +// GetInitializedAuthenticatorForAccount returns a single initialized authenticator for the account. +// It fetches the authenticator data from the store, gets the authenticator struct from the manager, +// then calls initialize on the authenticator data +func (k Keeper) GetInitializedAuthenticatorForAccount( + ctx sdk.Context, + account sdk.AccAddress, + selectedAuthenticator uint64, +) (authenticator.InitializedAuthenticator, error) { + // Get the authenticator data from the store + authenticatorFromStore, err := k.GetSelectedAuthenticatorData(ctx, account, selectedAuthenticator) + if err != nil { + return authenticator.InitializedAuthenticator{}, err + } + + uninitializedAuthenticator := k.authenticatorManager.GetAuthenticatorByType(authenticatorFromStore.Type) + if uninitializedAuthenticator == nil { + // This should never happen, but if it does, it means that stored authenticator is not registered + // or somehow the registered authenticator was removed / malformed + telemetry.IncrCounter(1, metrics.MissingRegisteredAuthenticator) + k.Logger(ctx).Error( + "account asscoicated authenticator not registered in manager", + "type", authenticatorFromStore.Type, + "id", selectedAuthenticator, + ) + + return authenticator.InitializedAuthenticator{}, + errors.Wrapf( + sdkerrors.ErrLogic, + "authenticator id %d failed to initialize, authenticator type %s not registered in manager", + selectedAuthenticator, authenticatorFromStore.Type, + ) + } + // Ensure that initialization of each authenticator works as expected + // NOTE: Always return a concrete authenticator not a pointer, do not modify in place + // NOTE: The authenticator manager returns a struct that is reused + initializedAuthenticator, err := uninitializedAuthenticator.Initialize(authenticatorFromStore.Config) + if err != nil { + return authenticator.InitializedAuthenticator{}, + errors.Wrapf( + err, + "authenticator %d with type %s failed to initialize", + selectedAuthenticator, authenticatorFromStore.Type, + ) + } + if initializedAuthenticator == nil { + return authenticator.InitializedAuthenticator{}, + errors.Wrapf( + types.ErrInitializingAuthenticator, + "authenticator.Initialize returned nil for %d with type %s", + selectedAuthenticator, authenticatorFromStore.Type, + ) + } + + finalAuthenticator := authenticator.InitializedAuthenticator{ + Id: authenticatorFromStore.Id, + Authenticator: initializedAuthenticator, + } + + return finalAuthenticator, nil +} + +// GetAuthenticatorDataForAccount gets all authenticators AccAddressFromBech32 with an account +// from the store. +func (k Keeper) GetAuthenticatorDataForAccount( + ctx sdk.Context, + account sdk.AccAddress, +) ([]*types.AccountAuthenticator, error) { + authenticators := make([]*types.AccountAuthenticator, 0) + + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.AuthenticatorKeyPrefix), + ) + iterator := storetypes.KVStorePrefixIterator(store, []byte(account.String())) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + authenticator, err := k.unmarshalAccountAuthenticator(iterator.Value()) + if err != nil { + return nil, err + } + authenticators = append(authenticators, authenticator) + } + + return authenticators, nil +} + +// unmarshalAccountAuthenticator is used to unmarshal the AccountAuthenticator from the store +func (k Keeper) unmarshalAccountAuthenticator(bz []byte) (*types.AccountAuthenticator, error) { + var accountAuthenticator types.AccountAuthenticator + err := k.cdc.Unmarshal(bz, &accountAuthenticator) + if err != nil { + return &types.AccountAuthenticator{}, errors.Wrap(err, "failed to unmarshal account authenticator") + } + return &accountAuthenticator, nil +} diff --git a/protocol/x/accountplus/keeper/keeper_test.go b/protocol/x/accountplus/keeper/keeper_test.go index 89deb898df..19f3991c89 100644 --- a/protocol/x/accountplus/keeper/keeper_test.go +++ b/protocol/x/accountplus/keeper/keeper_test.go @@ -135,3 +135,33 @@ func (s *KeeperTestSuite) TestKeeper_GetAndSetAuthenticatorId() { authenticatorId = s.tApp.App.AccountPlusKeeper.InitializeOrGetNextAuthenticatorId(ctx) s.Require().Equal(authenticatorId, uint64(2), "Initialize/Get authenticator id returned incorrect id") } + +func (s *KeeperTestSuite) TestKeeper_GetAuthenticatorDataForAccount() { + ctx := s.Ctx + + // Set up account + key := "6cf5103c60c939a5f38e383b52239c5296c968579eec1c68a47d70fbf1d19159" + bz, _ := hex.DecodeString(key) + priv := &secp256k1.PrivKey{Key: bz} + accAddress := sdk.AccAddress(priv.PubKey().Address()) + + _, err := s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + priv.PubKey().Bytes(), + ) + s.Require().NoError(err, "Should successfully add a SignatureVerification") + + _, err = s.tApp.App.AccountPlusKeeper.AddAuthenticator( + ctx, + accAddress, + "SignatureVerification", + priv.PubKey().Bytes(), + ) + s.Require().NoError(err, "Should successfully add a MessageFilter") + + authenticators, err := s.tApp.App.AccountPlusKeeper.GetAuthenticatorDataForAccount(ctx, accAddress) + s.Require().NoError(err) + s.Require().Equal(len(authenticators), 2, "Getting authenticators returning incorrect data") +} diff --git a/protocol/x/accountplus/keeper/query.go b/protocol/x/accountplus/keeper/query.go new file mode 100644 index 0000000000..0bbd00a257 --- /dev/null +++ b/protocol/x/accountplus/keeper/query.go @@ -0,0 +1,69 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types" +) + +var _ types.QueryServer = Keeper{} + +// GetAuthenticators returns all authenticators for an account. +func (k Keeper) GetAuthenticators( + ctx context.Context, + request *types.GetAuthenticatorsRequest, +) (*types.GetAuthenticatorsResponse, error) { + if request == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + acc, err := sdk.AccAddressFromBech32(request.Account) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + authenticators, err := k.GetAuthenticatorDataForAccount(sdkCtx, acc) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.GetAuthenticatorsResponse{AccountAuthenticators: authenticators}, nil +} + +// GetAuthenticator returns a specific authenticator for an account given its authenticator id. +func (k Keeper) GetAuthenticator( + ctx context.Context, + request *types.GetAuthenticatorRequest, +) (*types.GetAuthenticatorResponse, error) { + if request == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + acc, err := sdk.AccAddressFromBech32(request.Account) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + authenticator, err := k.GetSelectedAuthenticatorData(sdkCtx, acc, request.AuthenticatorId) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.GetAuthenticatorResponse{AccountAuthenticator: authenticator}, nil +} + +// GetParams returns the parameters for the accountplus module. +func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + + return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil +} diff --git a/protocol/x/accountplus/types/codec.go b/protocol/x/accountplus/types/codec.go index 994545c1e9..e3e58daf7d 100644 --- a/protocol/x/accountplus/types/codec.go +++ b/protocol/x/accountplus/types/codec.go @@ -5,6 +5,11 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" ) +// AuthenticatorTxOptions +type AuthenticatorTxOptions interface { + GetSelectedAuthenticators() []uint64 +} + func RegisterCodec(cdc *codec.LegacyAmino) {} func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { diff --git a/protocol/x/accountplus/types/errors.go b/protocol/x/accountplus/types/errors.go index 48ad01cbd6..54a23b0e51 100644 --- a/protocol/x/accountplus/types/errors.go +++ b/protocol/x/accountplus/types/errors.go @@ -18,4 +18,9 @@ var ( 3, "Authenticator data exceeds maximum length", ) + ErrInitializingAuthenticator = errorsmod.Register( + ModuleName, + 4, + "Error initializing authenticator", + ) ) From 5883104a768f7c10682677f4b97ec5de1e40d0de Mon Sep 17 00:00:00 2001 From: Tian Date: Tue, 24 Sep 2024 09:54:08 -0400 Subject: [PATCH 10/10] cap total size of vault orders in close only mode (#2329) --- protocol/x/vault/keeper/orders.go | 16 ++++++++---- protocol/x/vault/keeper/orders_test.go | 34 +++++++++++++------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/protocol/x/vault/keeper/orders.go b/protocol/x/vault/keeper/orders.go index 3e59423f19..311bbbbe38 100644 --- a/protocol/x/vault/keeper/orders.go +++ b/protocol/x/vault/keeper/orders.go @@ -384,11 +384,11 @@ func (k Keeper) GetVaultClobOrders( if vaultParams.Status == types.VaultStatus_VAULT_STATUS_CLOSE_ONLY { // In close-only mode with non-zero leverage. - reduceOnlyMaxOrderSize := k.GetVaultInventoryInPerpetual(ctx, vaultId, perpetual.Params.Id) + reduceOnlyTotalOrderSize := k.GetVaultInventoryInPerpetual(ctx, vaultId, perpetual.Params.Id) stepSize := lib.BigU(clobPair.StepBaseQuantums) - reduceOnlyMaxOrderSize.Quo(reduceOnlyMaxOrderSize, stepSize) - reduceOnlyMaxOrderSize.Mul(reduceOnlyMaxOrderSize, stepSize) - if reduceOnlyMaxOrderSize.Sign() == 0 { + reduceOnlyTotalOrderSize.Quo(reduceOnlyTotalOrderSize, stepSize) + reduceOnlyTotalOrderSize.Mul(reduceOnlyTotalOrderSize, stepSize) + if reduceOnlyTotalOrderSize.Sign() == 0 { return []*clobtypes.Order{}, nil } @@ -399,9 +399,15 @@ func (k Keeper) GetVaultClobOrders( reduceOnlySide = clobtypes.Order_SIDE_BUY } reduceOnlyOrders := make([]*clobtypes.Order, 0, len(orders)) + totalOrderSize := reduceOnlyTotalOrderSize.Uint64() for _, order := range orders { if order.Side == reduceOnlySide { - order.Quantums = lib.Min(order.Quantums, reduceOnlyMaxOrderSize.Uint64()) + if totalOrderSize == 0 { + break + } + + order.Quantums = lib.Min(order.Quantums, totalOrderSize) + totalOrderSize -= order.Quantums reduceOnlyOrders = append(reduceOnlyOrders, order) } } diff --git a/protocol/x/vault/keeper/orders_test.go b/protocol/x/vault/keeper/orders_test.go index 5e631e0b20..04df0a376d 100644 --- a/protocol/x/vault/keeper/orders_test.go +++ b/protocol/x/vault/keeper/orders_test.go @@ -1508,20 +1508,20 @@ func TestGetVaultClobOrders(t *testing.T) { expectedOrderQuantums: []uint64{}, }, "Success - Vault Clob 1, close-only status, 2 layers, leverage 0.6, sell orders only, " + - "order size capped to position size": { + "total size of orders capped to position size": { vaultStatus: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY, vaultQuotingParams: vaulttypes.QuotingParams{ Layers: 2, // 2 layers SpreadMinPpm: 7_654, // 76.54 bps SpreadBufferPpm: 2_900, // 29 bps SkewFactorPpm: 1_234_000, // 1.234 - OrderSizePctPpm: 1_000_000, // 100% + OrderSizePctPpm: 500_000, // 50% OrderExpirationSeconds: 4, // 4 seconds ActivationThresholdQuoteQuantums: dtypes.NewInt(1_000_000_000), }, vaultId: constants.Vault_Clob1, - vaultAssetQuoteQuantums: big.NewInt(500_000_000), // 500 USDC - vaultInventoryBaseQuantums: big.NewInt(250_000_000), // 0.25 ETH + vaultAssetQuoteQuantums: big.NewInt(1_000_000_000), // 1000 USDC + vaultInventoryBaseQuantums: big.NewInt(500_000_000), // 0.5 ETH clobPair: constants.ClobPair_Eth, marketParam: constants.TestMarketParams[1], marketPrice: constants.TestMarketPrices[1], @@ -1549,28 +1549,28 @@ func TestGetVaultClobOrders(t *testing.T) { expectedOrderSubticks: []uint64{ // spreadPpm = max(7_654, 2_900 + 50) = 7_654 // spread = 0.007654 - // open_notional = 250_000_000 * 10^-9 * 3_000 * 10^6 = 750_000_000 - // leverage = 750_000_000 / (500_000_000 + 750_000_000) = 0.6 + // open_notional = 500_000_000 * 10^-9 * 3_000 * 10^6 = 1_500_000_000 + // leverage = 1_500_000_000 / (1_000_000_000 + 1_500_000_000) = 0.6 // oracleSubticks = 3_000_000_000 * 10^(-6 - (-9) + (-9) - (-6)) = 3e9 - // leverage_0 = leverage - 0 * 1 = 0.6 + // leverage_0 = leverage - 0 * 0.5 = 0.6 // skew_ask_0 = -1.234 * 0.6 = -0.7404 // ask_spread_0 = (1 - 0.7404) * 0.007654 = 0.0019869784 // a_0 = 3e9 * (1 + 0.0019869784) = 3_005_960_935.2 ~= 3_005_961_000 (round up to 1000) 3_005_961_000, - // leverage_1 = leverage - 1 * 1 = -0.4 - // skew_ask_0 = -1.234 * -0.4 = 0.4936 - // ask_spread_0 = (1 + 0.4936) * 0.007654 = 0.0114320144 - // a_0 = 3e9 * (1 + 0.0114320144) = 3_034_296_043.2 ~= 3_034_297_000 (round up to 1000) - 3_034_297_000, + // leverage_1 = leverage - 1 * 0.5 = 0.1 + // skew_ask_0 = -1.234 * 0.1 = -0.1234 + // ask_spread_0 = (1 - 0.1234) * 0.007654 = 0.0067094964 + // a_0 = 3e9 * (1 + 0.0067094964) = 3020128489.2 ~= 3_020_129_000 (round up to 1000) + 3_020_129_000, }, - // order_size = 100% * 1250 / 3000 ~= 0.4166666667 + // order_size = 50% * 2500 / 3000 ~= 0.4166666667 // order_size_base_quantums = 0.4166666667e9 ~= 416_666_667 - // order_size_base_quantums = min(416_666_667, inventory) - // = min(416_666_667, 250_000_000) = 250_000_000 // round down to nearest multiple of step_base_quantums=1_000. expectedOrderQuantums: []uint64{ - 250_000_000, - 250_000_000, + 416_666_000, + // this order size is capped at `position size - sum of previous order sizes` + // = 500_000_000 - 416_666_000 = 83_334_000 + 83_334_000, }, expectedTimeInForce: []clobtypes.Order_TimeInForce{ clobtypes.Order_TIME_IN_FORCE_UNSPECIFIED,