Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
roy-dydx committed Apr 4, 2024
1 parent b5ed196 commit 2bfa258
Show file tree
Hide file tree
Showing 19 changed files with 8,776 additions and 1,519 deletions.
1 change: 1 addition & 0 deletions .github/workflows/protocol-build-and-push-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Protocol Build & Push Image to AWS ECR
on: # yamllint disable-line rule:truthy
push:
branches:
- roy/roy2
- main
- 'release/[a-z]+/v0.[0-9]+.x' # e.g. release/protocol/v0.1.x
- 'release/[a-z]+/v[0-9]+.x' # e.g. release/protocol/v1.x
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/protocol-build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Protocol Build & Push Image to AWS ECR
on: # yamllint disable-line rule:truthy
push:
branches:
- roy/roy2
- main
- 'release/[a-z]+/v0.[0-9]+.x' # e.g. release/protocol/v0.1.x
- 'release/[a-z]+/v[0-9]+.x' # e.g. release/protocol/v1.x
Expand Down
24 changes: 24 additions & 0 deletions protocol/lib/int256/int256.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,27 @@ func (z *Int) MulExp10(x *Int, y int64) *Int {
}
return z.Neg((*Int)(mulExp10((*uint256.Int)(z), (*uint256.Int)(z.Neg(x)), y)))
}

// --------------

func (z *Int) DivRoundUp(x *Int, y *Int) *Int {
_, m := (*uint256.Int)(z).DivMod(
(*uint256.Int)(x),
(*uint256.Int)(y),
new(uint256.Int),
)
if !m.IsZero() {
z.Add(z, OneInt256)
}
return z
}

func (z *Int) MulPpm(x *Int, ppm uint32) *Int {
result := z.Mul(x, NewUnsignedInt(uint64(ppm)))
return result.Div(result, OneMillionInt256)
}

func (z *Int) MulPpmRoundUp(x *Int, ppm uint32) *Int {
z.Mul(x, NewUnsignedInt(uint64(ppm)))
return z.DivRoundUp(z, OneMillionInt256)
}
27 changes: 27 additions & 0 deletions protocol/lib/quantums.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package lib

import (
"math/big"

"github.com/dydxprotocol/v4-chain/protocol/lib/int256"
)

// BaseToQuoteQuantums converts an amount denoted in base quantums, to an equivalent amount denoted in quote
Expand Down Expand Up @@ -37,6 +39,20 @@ func BaseToQuoteQuantums(
)
}

func BaseToQuoteQuantumsInt256(
baseQuantums *int256.Int,
baseCurrencyAtomicResolution int32,
priceValue uint64,
priceExponent int32,
) (bigNotional *int256.Int) {
return multiplyByPriceInt256(
baseQuantums,
baseCurrencyAtomicResolution,
priceValue,
priceExponent,
)
}

// QuoteToBaseQuantums converts an amount denoted in quote quantums, to an equivalent amount denoted in base
// quantums. To determine the equivalent amount, an oracle price is used.
//
Expand Down Expand Up @@ -117,6 +133,17 @@ func multiplyByPrice(
)
}

func multiplyByPriceInt256(
value *int256.Int,
baseCurrencyAtomicResolution int32,
priceValue uint64,
priceExponent int32,
) (result *int256.Int) {
result = int256.NewUnsignedInt(priceValue)
result.Mul(result, value)
return result.MulExp10(result, int64(priceExponent+baseCurrencyAtomicResolution-QuoteCurrencyAtomicResolution))
}

// FundingRateToIndex converts funding rate (in ppm) to FundingIndex given the oracle price.
//
// To get funding index from funding rate, we know that:
Expand Down
86 changes: 86 additions & 0 deletions protocol/lib/quantums_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/dydxprotocol/v4-chain/protocol/lib"
"github.com/dydxprotocol/v4-chain/protocol/lib/int256"
big_testutil "github.com/dydxprotocol/v4-chain/protocol/testutil/big"
)

Expand Down Expand Up @@ -108,6 +109,91 @@ func TestBaseToQuoteQuantums(t *testing.T) {
}
}

func TestBaseToQuoteQuantumsInt256(t *testing.T) {
tests := map[string]struct {
baseQuantums *int256.Int
baseCurrencyAtomicResolution int32
priceValue uint64
priceExponent int32
bigExpectedQuoteQuantums *int256.Int
}{
"Converts from base to quote quantums": {
baseQuantums: int256.NewInt(1),
baseCurrencyAtomicResolution: -6,
priceValue: 1,
priceExponent: 1,
bigExpectedQuoteQuantums: int256.NewInt(10),
},
"Correctly converts negative value": {
baseQuantums: int256.NewInt(-100),
baseCurrencyAtomicResolution: -6,
priceValue: 1,
priceExponent: 1,
bigExpectedQuoteQuantums: int256.NewInt(-1000),
},
"priceExponent is negative": {
baseQuantums: int256.NewInt(5_000_000),
baseCurrencyAtomicResolution: -6,
priceValue: 7,
priceExponent: -5,
bigExpectedQuoteQuantums: int256.NewInt(350),
},
"priceExponent is zero": {
baseQuantums: int256.NewInt(5_000_000),
baseCurrencyAtomicResolution: -6,
priceValue: 7,
priceExponent: 0,
bigExpectedQuoteQuantums: int256.NewInt(35_000_000),
},
"baseCurrencyAtomicResolution is greater than 10^6": {
baseQuantums: int256.NewInt(5_000_000),
baseCurrencyAtomicResolution: -8,
priceValue: 7,
priceExponent: 0,
bigExpectedQuoteQuantums: int256.NewInt(350_000),
},
"baseCurrencyAtomicResolution is less than 10^6": {
baseQuantums: int256.NewInt(5_000_000),
baseCurrencyAtomicResolution: -4,
priceValue: 7,
priceExponent: 1,
bigExpectedQuoteQuantums: int256.NewInt(35_000_000_000),
},
"Calculation rounds down": {
baseQuantums: int256.NewInt(9),
baseCurrencyAtomicResolution: -8,
priceValue: 1,
priceExponent: 1,
bigExpectedQuoteQuantums: int256.NewInt(0),
},
"Negative calculation rounds up": {
baseQuantums: int256.NewInt(-9),
baseCurrencyAtomicResolution: -8,
priceValue: 1,
priceExponent: 1,
bigExpectedQuoteQuantums: int256.NewInt(0),
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
quoteQuantums := lib.BaseToQuoteQuantumsInt256(
tc.baseQuantums,
tc.baseCurrencyAtomicResolution,
tc.priceValue,
tc.priceExponent,
)
if !tc.bigExpectedQuoteQuantums.Eq(quoteQuantums) {
t.Fatalf(
"%s: expectedQuoteQuantums: %s, quoteQuantums: %s",
name,
tc.bigExpectedQuoteQuantums.String(),
quoteQuantums.String(),
)
}
})
}
}

func TestQuoteToBaseQuantums(t *testing.T) {
tests := map[string]struct {
bigQuoteQuantums *big.Int
Expand Down
67 changes: 67 additions & 0 deletions protocol/x/assets/keeper/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events"
"github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager"
"github.com/dydxprotocol/v4-chain/protocol/lib"
"github.com/dydxprotocol/v4-chain/protocol/lib/int256"
"github.com/dydxprotocol/v4-chain/protocol/x/assets/types"
)

Expand Down Expand Up @@ -218,6 +219,41 @@ func (k Keeper) GetNetCollateral(
return big.NewInt(0), types.ErrNotImplementedMargin
}

// GetNetCollateral returns the net collateral that a given position (quantums)
// for a given assetId contributes to an account.
func (k Keeper) GetNetCollateralInt256(
ctx sdk.Context,
id uint32,
quantums *int256.Int,
) (
netCollateralQuoteQuantums *int256.Int,
err error,
) {
if id == types.AssetUsdc.Id {
return new(int256.Int).Set(quantums), nil
}

// Get asset
_, exists := k.GetAsset(ctx, id)
if !exists {
return int256.NewInt(0), errorsmod.Wrap(types.ErrAssetDoesNotExist, lib.UintToString(id))
}

if quantums.IsZero() {
return int256.NewInt(0), nil
}

// Balance is positive.
// TODO(DEC-581): add multi-collateral support.
if quantums.Sign() == 1 {
return int256.NewInt(0), types.ErrNotImplementedMulticollateral
}

// Balance is negative.
// TODO(DEC-582): add margin-trading support.
return int256.NewInt(0), types.ErrNotImplementedMargin
}

// GetMarginRequirements returns the initial and maintenance margin-
// requirements for a given position size for a given assetId.
func (k Keeper) GetMarginRequirements(
Expand Down Expand Up @@ -251,6 +287,37 @@ func (k Keeper) GetMarginRequirements(
return big.NewInt(0), big.NewInt(0), types.ErrNotImplementedMargin
}

func (k Keeper) GetMarginRequirementsInt256(
ctx sdk.Context,
id uint32,
bigQuantums *int256.Int,
) (
bigInitialMarginQuoteQuantums *int256.Int,
bigMaintenanceMarginQuoteQuantums *int256.Int,
err error,
) {
// QuoteBalance does not contribute to any margin requirements.
if id == types.AssetUsdc.Id {
return int256.NewInt(0), int256.NewInt(0), nil
}

// Get asset
_, exists := k.GetAsset(ctx, id)
if !exists {
return int256.NewInt(0), int256.NewInt(0), errorsmod.Wrap(
types.ErrAssetDoesNotExist, lib.UintToString(id))
}

// Balance is zero or positive.
if bigQuantums.Sign() >= 0 {
return int256.NewInt(0), int256.NewInt(0), nil
}

// Balance is negative.
// TODO(DEC-582): margin-trading
return int256.NewInt(0), int256.NewInt(0), types.ErrNotImplementedMargin
}

// ConvertAssetToCoin converts the given `assetId` and `quantums` used in `x/asset`,
// to an `sdk.Coin` in correspoding `denom` and `amount` used in `x/bank`.
// Also outputs `convertedQuantums` which has the equal value as converted `sdk.Coin`.
Expand Down
5 changes: 3 additions & 2 deletions protocol/x/clob/keeper/equity_tier_limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dydxprotocol/v4-chain/protocol/lib"
"github.com/dydxprotocol/v4-chain/protocol/lib/int256"
"github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types"
)
Expand Down Expand Up @@ -63,7 +64,7 @@ func (k Keeper) getEquityTierLimitForSubaccount(
ctx sdk.Context, subaccountId satypes.SubaccountId,
equityTierLimits []types.EquityTierLimit,
) (equityTier types.EquityTierLimit, bigNetCollateral *big.Int, err error) {
netCollateral, _, _, err := k.subaccountsKeeper.GetNetCollateralAndMarginRequirements(
netCollateral, _, _, err := k.subaccountsKeeper.GetNetCollateralAndMarginRequirementsInt256(
ctx,
satypes.Update{
SubaccountId: subaccountId,
Expand All @@ -75,7 +76,7 @@ func (k Keeper) getEquityTierLimitForSubaccount(

var equityTierLimit types.EquityTierLimit
for _, limit := range equityTierLimits {
if netCollateral.Cmp(limit.UsdTncRequired.BigInt()) < 0 {
if netCollateral.Cmp(int256.MustFromBig(limit.UsdTncRequired.BigInt())) < 0 {
break
}
equityTierLimit = limit
Expand Down
2 changes: 1 addition & 1 deletion protocol/x/clob/keeper/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ func (k Keeper) AddOrderToOrderbookCollatCheck(
metrics.Latency,
)

success, successPerSubaccountUpdate, err := k.subaccountsKeeper.CanUpdateSubaccounts(
success, successPerSubaccountUpdate, err := k.subaccountsKeeper.CanUpdateSubaccountsInt256(
ctx,
updates,
satypes.CollatCheck,
Expand Down
2 changes: 1 addition & 1 deletion protocol/x/clob/keeper/process_single_match.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ func (k Keeper) persistMatchedOrders(
}

// Apply the update.
success, successPerUpdate, err := k.subaccountsKeeper.UpdateSubaccounts(
success, successPerUpdate, err := k.subaccountsKeeper.UpdateSubaccountsInt256(
ctx,
updates,
satypes.Match,
Expand Down
28 changes: 28 additions & 0 deletions protocol/x/clob/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/rand"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dydxprotocol/v4-chain/protocol/lib/int256"
assettypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types"
blocktimetypes "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/types"
perpetualsmoduletypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types"
Expand All @@ -23,6 +24,15 @@ type SubaccountsKeeper interface {
successPerUpdate []satypes.UpdateResult,
err error,
)
CanUpdateSubaccountsInt256(
ctx sdk.Context,
updates []satypes.Update,
updateType satypes.UpdateType,
) (
success bool,
successPerUpdate []satypes.UpdateResult,
err error,
)
GetNetCollateralAndMarginRequirements(
ctx sdk.Context,
update satypes.Update,
Expand All @@ -32,6 +42,15 @@ type SubaccountsKeeper interface {
bigMaintenanceMargin *big.Int,
err error,
)
GetNetCollateralAndMarginRequirementsInt256(
ctx sdk.Context,
update satypes.Update,
) (
bigNetCollateral *int256.Int,
bigInitialMargin *int256.Int,
bigMaintenanceMargin *int256.Int,
err error,
)
GetSubaccount(
ctx sdk.Context,
id satypes.SubaccountId,
Expand Down Expand Up @@ -59,6 +78,15 @@ type SubaccountsKeeper interface {
successPerUpdate []satypes.UpdateResult,
err error,
)
UpdateSubaccountsInt256(
ctx sdk.Context,
updates []satypes.Update,
updateType satypes.UpdateType,
) (
success bool,
successPerUpdate []satypes.UpdateResult,
err error,
)
SetNegativeTncSubaccountSeenAtBlock(
ctx sdk.Context,
perpetualId uint32,
Expand Down
Loading

0 comments on commit 2bfa258

Please sign in to comment.