Skip to content

Commit

Permalink
Clean subaccounts/lib/updates.go codepaths (#1767)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrendanChou authored Jun 25, 2024
1 parent d36863c commit ce92609
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 262 deletions.
4 changes: 1 addition & 3 deletions protocol/daemons/liquidation/client/sub_task_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,7 @@ func (c *Client) CheckSubaccountCollateralization(
)

risk, err := salib.GetRiskForSubaccount(
satypes.SettledUpdate{
SettledSubaccount: settledSubaccount,
},
settledSubaccount,
perpInfos,
)

Expand Down
27 changes: 12 additions & 15 deletions protocol/x/subaccounts/keeper/subaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,13 @@ func (k Keeper) UpdateSubaccounts(
}
}

// Apply the updates to perpetual positions.
salib.UpdatePerpetualPositions(
settledUpdates,
perpInfos,
)

// Apply the updates to asset positions.
salib.UpdateAssetPositions(settledUpdates)
// Apply the updates to asset positions and perpetual positions.
for i := range settledUpdates {
settledUpdates[i].SettledSubaccount = salib.CalculateUpdatedSubaccount(
settledUpdates[i],
perpInfos,
)
}

// Transfer collateral between collateral pools for any isolated perpetual positions that changed
// state due to an update.
Expand Down Expand Up @@ -590,8 +589,9 @@ func (k Keeper) internalCanUpdateSubaccounts(
}

// Get the new collateralization and margin requirements with the update applied.
updatedSubaccount := salib.CalculateUpdatedSubaccount(u, perpInfos)
riskNew, err := salib.GetRiskForSubaccount(
u,
updatedSubaccount,
perpInfos,
)
if err != nil {
Expand All @@ -604,10 +604,6 @@ func (k Keeper) internalCanUpdateSubaccounts(
// We must now check if the state transition is valid.
if !riskNew.IsInitialCollateralized() {
// Get the current collateralization and margin requirements without the update applied.
emptyUpdate := types.SettledUpdate{
SettledSubaccount: u.SettledSubaccount,
}

bytes, err := proto.Marshal(u.SettledSubaccount.Id)
if err != nil {
return false, nil, err
Expand All @@ -617,7 +613,7 @@ func (k Keeper) internalCanUpdateSubaccounts(
// Cache the current collateralization and margin requirements for the subaccount.
if _, ok := riskCurMap[saKey]; !ok {
riskCurMap[saKey], err = salib.GetRiskForSubaccount(
emptyUpdate,
u.SettledSubaccount,
perpInfos,
)
if err != nil {
Expand Down Expand Up @@ -673,9 +669,10 @@ func (k Keeper) GetNetCollateralAndMarginRequirements(
AssetUpdates: update.AssetUpdates,
PerpetualUpdates: update.PerpetualUpdates,
}
updatedSubaccount := salib.CalculateUpdatedSubaccount(settledUpdate, perpInfos)

return salib.GetRiskForSubaccount(
settledUpdate,
updatedSubaccount,
perpInfos,
)
}
Expand Down
55 changes: 39 additions & 16 deletions protocol/x/subaccounts/keeper/subaccount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,30 +512,42 @@ func TestUpdateSubaccounts(t *testing.T) {
},
msgSenderEnabled: true,
},
"multiple updates for same position not allowed": {
"multiple updates for same position handled gracefully": {
expectedQuoteBalance: big.NewInt(0),
expectedSuccess: false,
expectedSuccessPerUpdate: nil,
expectedErr: types.ErrNonUniqueUpdatesPosition,
expectedSuccess: true,
expectedSuccessPerUpdate: []types.UpdateResult{types.Success},
perpetuals: []perptypes.Perpetual{
constants.BtcUsd_SmallMarginRequirement,
},
perpetualPositions: []*types.PerpetualPosition{
&constants.PerpetualPosition_OneBTCLong,
},
expectedPerpetualPositions: []*types.PerpetualPosition{
&constants.PerpetualPosition_OneBTCLong,
{
PerpetualId: uint32(0),
Quantums: dtypes.NewInt(300_000_000), // 3 BTC
FundingIndex: dtypes.NewInt(0),
},
},
expectedUpdatedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{
defaultSubaccountId: {
&types.PerpetualPosition{
PerpetualId: uint32(0),
Quantums: dtypes.NewInt(300_000_000), // 3 BTC
FundingIndex: dtypes.NewInt(0),
},
},
},
updates: []types.Update{
{
PerpetualUpdates: []types.PerpetualUpdate{
{
PerpetualId: uint32(0),
BigQuantumsDelta: big.NewInt(9_900_000_000), // 99 BTC
BigQuantumsDelta: big.NewInt(100_000_000),
},
{
PerpetualId: uint32(0),
BigQuantumsDelta: big.NewInt(9_900_000_000), // 99 BTC
BigQuantumsDelta: big.NewInt(100_000_000),
},
},
},
Expand Down Expand Up @@ -4797,7 +4809,6 @@ func TestCanUpdateSubaccounts(t *testing.T) {
expectedSuccessPerUpdate: []types.UpdateResult{types.Success},
},
"update refers to the same position twice": {
expectedErr: types.ErrNonUniqueUpdatesPosition,
perpetuals: []perptypes.Perpetual{
constants.BtcUsd_SmallMarginRequirement,
},
Expand All @@ -4816,6 +4827,8 @@ func TestCanUpdateSubaccounts(t *testing.T) {
},
},
},
expectedSuccess: true,
expectedSuccessPerUpdate: []types.UpdateResult{types.Success},
},
"multiple updates are considered independently for same account": {
expectedSuccess: false,
Expand Down Expand Up @@ -5638,29 +5651,35 @@ func TestGetNetCollateralAndMarginRequirements(t *testing.T) {
},
},
"multiple asset updates for the same position": {
expectedErr: types.ErrNonUniqueUpdatesPosition,
perpetuals: []perptypes.Perpetual{
constants.BtcUsd_NoMarginRequirement,
},
assetPositions: []*types.AssetPosition{
&constants.Usdc_Asset_100_000,
&constants.Short_Asset_1BTC,
},
assetUpdates: []types.AssetUpdate{
{
AssetId: constants.BtcUsd.Id,
BigQuantumsDelta: big.NewInt(-100_000_000), // -1 BTC
AssetId: constants.Usdc.Id,
BigQuantumsDelta: big.NewInt(1_000_000), // +1 USDC
},
{
AssetId: constants.BtcUsd.Id,
BigQuantumsDelta: big.NewInt(-100_000_000), // -1 BTC
AssetId: constants.Usdc.Id,
BigQuantumsDelta: big.NewInt(1_000_000), // +1 USDC
},
},
expectedNetCollateral: big.NewInt(100_002_000_000), // $100,000 + $1 + $1
expectedInitialMargin: big.NewInt(0), // $0
expectedMaintenanceMargin: big.NewInt(0), // $0
},
"multiple perpetual updates for the same position": {
expectedErr: types.ErrNonUniqueUpdatesPosition,
useEmptySubaccount: true,
assetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(1_000_000)),
expectedNetCollateral: big.NewInt(-99_249_000_000), // $1 - $100,000 (BTC update) + $750 (ETH update)
expectedInitialMargin: big.NewInt(50_150_000_000), // $50,000 (BTC update) + $150 (ETH update)
expectedMaintenanceMargin: big.NewInt(40_075_000_000), // $40,000 (BTC update) + $75 (ETH update)
perpetuals: []perptypes.Perpetual{
constants.BtcUsd_NoMarginRequirement,
constants.BtcUsd_50PercentInitial_40PercentMaintenance,
constants.EthUsd_20PercentInitial_10PercentMaintenance,
},
perpetualPositions: []*types.PerpetualPosition{
&constants.PerpetualPosition_OneBTCLong,
Expand All @@ -5674,6 +5693,10 @@ func TestGetNetCollateralAndMarginRequirements(t *testing.T) {
PerpetualId: uint32(0),
BigQuantumsDelta: big.NewInt(-100_000_000), // -1 BTC
},
{
PerpetualId: uint32(1),
BigQuantumsDelta: big.NewInt(250_000_000), // .25 ETH
},
},
},
"speculative update to non-existent subaccount": {
Expand Down
Loading

0 comments on commit ce92609

Please sign in to comment.