Skip to content

Commit

Permalink
resolve comments
Browse files Browse the repository at this point in the history
  • Loading branch information
0xshinobii committed Mar 21, 2024
1 parent 64f4ea2 commit 3e524b7
Show file tree
Hide file tree
Showing 16 changed files with 108 additions and 140 deletions.
8 changes: 3 additions & 5 deletions plugin/evm/orderbook/hubbleutils/data_structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ const (
Min_Allowable_Margin
)

type MarginType = uint8

const (
Cross_Margin MarginType = iota
Isolated_Margin
Cross MarginMode = iota
Isolated
)

type AccountPreferences struct {
MarginType MarginType
MarginMode MarginMode
MarginFraction *big.Int
}

Expand Down
14 changes: 7 additions & 7 deletions plugin/evm/orderbook/hubbleutils/margin_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ type HubbleState struct {
}

type UserState struct {
Positions map[Market]*Position
ReduceOnlyAmounts []*big.Int
Margins []*big.Int
PendingFunding *big.Int
ReservedMargin *big.Int
Positions map[Market]*Position
ReduceOnlyAmounts []*big.Int
Margins []*big.Int
PendingFunding *big.Int
ReservedMargin *big.Int
AccountPreferences map[Market]*AccountPreferences
}

Expand Down Expand Up @@ -132,7 +132,7 @@ func GetCrossMarginAccountData(hState *HubbleState, userState *UserState) (*big.
requiredMargin := big.NewInt(0)

for _, market := range hState.ActiveMarkets {
if userState.AccountPreferences[market].MarginType == Cross_Margin {
if userState.AccountPreferences[market].MarginMode == Cross {
_notionalPosition, _unrealizedPnl, _requiredMargin := GetTraderPositionDetails(userState.Positions[market], hState.OraclePrices[market], userState.AccountPreferences[market].MarginFraction)
notionalPosition.Add(notionalPosition, _notionalPosition)
unrealizedPnl.Add(unrealizedPnl, _unrealizedPnl)
Expand All @@ -148,7 +148,7 @@ func GetTraderPositionDetails(position *Position, oraclePrice *big.Int, marginFr
}

// based on oracle price,
notionalPosition, unrealizedPnl, _ := GetPositionMetadata(
notionalPosition, unrealizedPnl, _ := GetPositionMetadata(
oraclePrice,
position.OpenNotional,
position.Size,
Expand Down
6 changes: 3 additions & 3 deletions plugin/evm/orderbook/hubbleutils/margin_math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ var userState = &UserState{
ReservedMargin: big.NewInt(60 * 1e6), // 60
AccountPreferences: map[Market]*AccountPreferences{
0: {
MarginType: Cross_Margin,
MarginMode: Cross,
MarginFraction: big.NewInt(0.2 * 1e6), // 0.2
},
1: {
MarginType: Isolated_Margin,
MarginMode: Isolated,
MarginFraction: big.NewInt(0.1 * 1e6), // 0.1
},
},
Expand Down Expand Up @@ -264,7 +264,7 @@ func TestGetNotionalPositionAndRequiredMargin(t *testing.T) {
})

t.Run("both markets in cross mode", func(t *testing.T) {
userState.AccountPreferences[1].MarginType = Cross_Margin
userState.AccountPreferences[1].MarginMode = Cross
notionalPosition, margin, requiredMargin := GetNotionalPositionAndRequiredMargin(_hState, userState)
expectedNotionalPosition := big.NewInt(0)
expectedRequiredMargin := big.NewInt(0)
Expand Down
60 changes: 25 additions & 35 deletions precompile/contracts/bibliophile/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ import (
)

const (
VAR_POSITIONS_SLOT int64 = 1
VAR_CUMULATIVE_PREMIUM_FRACTION int64 = 2
MAX_ORACLE_SPREAD_RATIO_SLOT int64 = 3
MAX_LIQUIDATION_RATIO_SLOT int64 = 4
MIN_SIZE_REQUIREMENT_SLOT int64 = 5
UNDERLYING_ASSET_SLOT int64 = 6
MAX_LIQUIDATION_PRICE_SPREAD int64 = 11
MULTIPLIER_SLOT int64 = 12
IMPACT_MARGIN_NOTIONAL_SLOT int64 = 19
LAST_TRADE_PRICE_SLOT int64 = 20
BIDS_SLOT int64 = 21
ASKS_SLOT int64 = 22
BIDS_HEAD_SLOT int64 = 23
ASKS_HEAD_SLOT int64 = 24
TRADE_MARGIN_FRACTION_SLOT int64 = 28
LIQUIDATION_MARGIN_FRACTION_SLOT int64 = 29
ISOLATED_TRADE_MARGIN_FRACTION_SLOT int64 = 30
VAR_POSITIONS_SLOT int64 = 1
VAR_CUMULATIVE_PREMIUM_FRACTION int64 = 2
MAX_ORACLE_SPREAD_RATIO_SLOT int64 = 3
MAX_LIQUIDATION_RATIO_SLOT int64 = 4
MIN_SIZE_REQUIREMENT_SLOT int64 = 5
UNDERLYING_ASSET_SLOT int64 = 6
MAX_LIQUIDATION_PRICE_SPREAD int64 = 11
MULTIPLIER_SLOT int64 = 12
IMPACT_MARGIN_NOTIONAL_SLOT int64 = 19
LAST_TRADE_PRICE_SLOT int64 = 20
BIDS_SLOT int64 = 21
ASKS_SLOT int64 = 22
BIDS_HEAD_SLOT int64 = 23
ASKS_HEAD_SLOT int64 = 24
TRADE_MARGIN_FRACTION_SLOT int64 = 28
LIQUIDATION_MARGIN_FRACTION_SLOT int64 = 29
ISOLATED_TRADE_MARGIN_FRACTION_SLOT int64 = 30
ISOLATED_LIQUIDATION_MARGIN_FRACTION_SLOT int64 = 31
ACCOUNT_PREFERENCES_SLOT int64 = 33
MAX_POSITION_CAP_SLOT int64 = 34
ACCOUNT_PREFERENCES_SLOT int64 = 33
MAX_POSITION_CAP_SLOT int64 = 34
)

// AMM State
Expand Down Expand Up @@ -172,11 +172,11 @@ func accountPreferencesSlot(trader *common.Address) *big.Int {
return new(big.Int).SetBytes(crypto.Keccak256(append(common.LeftPadBytes(trader.Bytes(), 32), common.LeftPadBytes(big.NewInt(ACCOUNT_PREFERENCES_SLOT).Bytes(), 32)...)))
}

func getMarginType(stateDB contract.StateDB, market common.Address, trader *common.Address) uint8 {
func getMarginMode(stateDB contract.StateDB, market common.Address, trader *common.Address) uint8 {
return uint8(stateDB.GetState(market, common.BigToHash(accountPreferencesSlot(trader))).Big().Uint64())
}

func traderMarginFraction(stateDB contract.StateDB, market common.Address, trader *common.Address) *big.Int {
func marginFraction(stateDB contract.StateDB, market common.Address, trader *common.Address) *big.Int {
return stateDB.GetState(market, common.BigToHash(new(big.Int).Add(accountPreferencesSlot(trader), big.NewInt(1)))).Big()
}

Expand All @@ -186,7 +186,7 @@ func getMaxPositionCap(stateDB contract.StateDB, market common.Address) *big.Int

func getMarginFractionByMode(stateDB contract.StateDB, market common.Address, trader *common.Address, mode uint8) *big.Int {
if mode == hu.Maintenance_Margin {
if (getMarginType(stateDB, market, trader) == hu.Isolated_Margin) {
if getMarginMode(stateDB, market, trader) == hu.Isolated {
return getIsolatedLiquidationMarginFraction(stateDB, market)
} else {
return getLiquidationMarginFraction(stateDB, market)
Expand All @@ -198,26 +198,16 @@ func getMarginFractionByMode(stateDB contract.StateDB, market common.Address, tr
}

func getTraderMarginFraction(stateDB contract.StateDB, market common.Address, trader *common.Address) *big.Int {
traderMarginFraction_ := traderMarginFraction(stateDB, market, trader)
if (traderMarginFraction_.Cmp(big.NewInt(0)) != 0) {
traderMarginFraction_ := marginFraction(stateDB, market, trader)
if traderMarginFraction_.Sign() != 0 {
return traderMarginFraction_
} else if (getMarginType(stateDB, market, trader) == hu.Isolated_Margin) {
} else if getMarginMode(stateDB, market, trader) == hu.Isolated {
return getIsolatedTradeMarginFraction(stateDB, market)
} else {
return getTradeMarginFraction(stateDB, market)
}
}

func getRequiredMargin(stateDB contract.StateDB, baseAsset *big.Int, price *big.Int, marketId int64, trader *common.Address) *big.Int {
quoteAsset := hu.Div1e18(hu.Mul(hu.Abs(baseAsset), price))
return getRequiredMarginForQuote(stateDB, GetMarketAddressFromMarketID(marketId, stateDB), trader, quoteAsset)
}

func getRequiredMarginForQuote(stateDB contract.StateDB, market common.Address, trader *common.Address, quote *big.Int) *big.Int {
marginFraction := getTraderMarginFraction(stateDB, market, trader)
return hu.Div1e6(hu.Mul(quote, marginFraction))
}

func getPositionCap(stateDB contract.StateDB, market int64, trader *common.Address) *big.Int {
marketAddress := GetMarketAddressFromMarketID(market, stateDB)
maxPositionCap := getMaxPositionCap(stateDB, marketAddress)
Expand Down
39 changes: 12 additions & 27 deletions precompile/contracts/bibliophile/clearing_house.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type GetTraderDataForMarketOutput struct {
RequiredMargin *big.Int
UnrealizedPnl *big.Int
PendingFunding *big.Int
IsIsolated bool
IsIsolated bool
}

func getNotionalPositionAndMargin(stateDB contract.StateDB, input *GetNotionalPositionAndMarginInput, upgradeVersion hu.UpgradeVersion) GetNotionalPositionAndMarginOutput {
Expand Down Expand Up @@ -114,46 +114,32 @@ func getNotionalPositionAndMargin(stateDB contract.StateDB, input *GetNotionalPo
}

func getNotionalPositionAndRequiredMargin(stateDB contract.StateDB, input *GetNotionalPositionAndMarginInput) GetNotionalPositionAndMarginOutput {
positions, underlyingPrices, accountPreferences, activeMarketIds := getMarketsDataFromDB(stateDB, &input.Trader, input.Mode)
pendingFunding := big.NewInt(0)
margin := GetNormalizedMargin(stateDB, input.Trader)
accountData := getCrossMarginAccountData(stateDB, &input.Trader, input.Mode)
if input.IncludeFundingPayments {
pendingFunding = getTotalFundingForCrossMarginPositions(stateDB, &input.Trader)
margin.Sub(margin, accountData.PendingFunding)
}
notionalPosition, margin, requiredMargin := hu.GetNotionalPositionAndRequiredMargin(
&hu.HubbleState{
Assets: GetCollaterals(stateDB),
OraclePrices: underlyingPrices,
ActiveMarkets: activeMarketIds,
},
&hu.UserState{
Positions: positions,
Margins: getMargins(stateDB, input.Trader),
PendingFunding: pendingFunding,
AccountPreferences: accountPreferences,
},
)
return GetNotionalPositionAndMarginOutput{
NotionalPosition: notionalPosition,
NotionalPosition: accountData.NotionalPosition,
Margin: margin,
RequiredMargin: requiredMargin,
RequiredMargin: accountData.RequiredMargin,
}
}

func getCrossMarginAccountData(stateDB contract.StateDB, trader *common.Address, mode uint8, upgradeVersion hu.UpgradeVersion) GetTraderDataForMarketOutput {
func getCrossMarginAccountData(stateDB contract.StateDB, trader *common.Address, mode uint8) GetTraderDataForMarketOutput {
positions, underlyingPrices, accountPreferences, activeMarketIds := getMarketsDataFromDB(stateDB, trader, mode)
notionalPosition, requiredMargin, unrealizedPnl := hu.GetCrossMarginAccountData(
&hu.HubbleState{
ActiveMarkets: activeMarketIds,
OraclePrices: underlyingPrices,
UpgradeVersion: upgradeVersion,
},
&hu.UserState{
Positions: positions,
AccountPreferences: accountPreferences,
},
)
pendingFunding := getTotalFundingForCrossMarginPositions(stateDB, trader)
return GetTraderDataForMarketOutput {
return GetTraderDataForMarketOutput{
NotionalPosition: notionalPosition,
RequiredMargin: requiredMargin,
UnrealizedPnl: unrealizedPnl,
Expand All @@ -169,11 +155,10 @@ func getMarketsDataFromDB(stateDB contract.StateDB, trader *common.Address, mode
accountPreferences = make(map[int]*hu.AccountPreferences, numMarkets)
activeMarketIds = make([]int, numMarkets)
for i, market := range markets {
// @todo can use `market` instead of `GetMarketAddressFromMarketID`?
positions[i] = getPosition(stateDB, GetMarketAddressFromMarketID(int64(i), stateDB), trader)
positions[i] = getPosition(stateDB, market, trader)
underlyingPrices[i] = getUnderlyingPrice(stateDB, market)
activeMarketIds[i] = i
accountPreferences[i].MarginType = getMarginType(stateDB, market, trader)
accountPreferences[i].MarginMode = getMarginMode(stateDB, market, trader)
accountPreferences[i].MarginFraction = getMarginFractionByMode(stateDB, market, trader, mode)
}
return positions, underlyingPrices, accountPreferences, activeMarketIds
Expand All @@ -182,7 +167,7 @@ func getMarketsDataFromDB(stateDB contract.StateDB, trader *common.Address, mode
func getTotalFundingForCrossMarginPositions(stateDB contract.StateDB, trader *common.Address) *big.Int {
totalFunding := big.NewInt(0)
for _, market := range GetMarkets(stateDB) {
if getMarginType(stateDB, market, trader) == hu.Cross_Margin {
if getMarginMode(stateDB, market, trader) == hu.Cross {
totalFunding.Add(totalFunding, getPendingFundingPayment(stateDB, market, trader))
}
}
Expand All @@ -196,7 +181,7 @@ func getTraderDataForMarket(stateDB contract.StateDB, trader *common.Address, ma
underlyingPrice := getUnderlyingPrice(stateDB, market)
notionalPosition, unrealizedPnl, requiredMargin := hu.GetTraderPositionDetails(position, underlyingPrice, marginFraction)
pendingFunding := getPendingFundingPayment(stateDB, market, trader)
isIsolated := getMarginType(stateDB, market, trader) == hu.Isolated_Margin
isIsolated := getMarginMode(stateDB, market, trader) == hu.Isolated
return GetTraderDataForMarketOutput{
IsIsolated: isIsolated,
NotionalPosition: notionalPosition,
Expand Down
12 changes: 6 additions & 6 deletions precompile/contracts/bibliophile/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ type BibliophileClient interface {
GetUpperAndLowerBoundForMarket(marketId int64) (*big.Int, *big.Int)
GetAcceptableBoundsForLiquidation(marketId int64) (*big.Int, *big.Int)
GetPositionCap(marketId int64, trader common.Address) *big.Int
GetTraderMarginFraction(market common.Address, trader *common.Address) *big.Int

GetTimeStamp() uint64
GetNotionalPositionAndMargin(trader common.Address, includeFundingPayments bool, mode uint8, upgradeVersion hu.UpgradeVersion) (*big.Int, *big.Int)
GetNotionalPositionAndRequiredMargin(trader common.Address, includeFundingPayments bool, mode uint8) (*big.Int, *big.Int, *big.Int)
GetCrossMarginAccountData(trader common.Address, mode uint8, upgradeVersion hu.UpgradeVersion) (*big.Int, *big.Int, *big.Int, *big.Int)
GetCrossMarginAccountData(trader common.Address, mode uint8) (*big.Int, *big.Int, *big.Int, *big.Int)
GetTotalFundingForCrossMarginPositions(trader *common.Address) *big.Int
GetTraderDataForMarket(trader common.Address, marketId int64, mode uint8) (bool, *big.Int, *big.Int, *big.Int, *big.Int)
GetRequiredMargin(baseAsset *big.Int, price *big.Int, marketId int64, trader *common.Address) *big.Int
HasReferrer(trader common.Address) bool
GetActiveMarketsCount() int64

Expand Down Expand Up @@ -224,8 +224,8 @@ func (b *bibliophileClient) GetNotionalPositionAndRequiredMargin(trader common.A
return output.NotionalPosition, output.Margin, output.RequiredMargin
}

func (b *bibliophileClient) GetCrossMarginAccountData(trader common.Address, mode uint8, upgradeVersion hu.UpgradeVersion) (*big.Int, *big.Int, *big.Int, *big.Int) {
output := getCrossMarginAccountData(b.accessibleState.GetStateDB(), &trader, mode, upgradeVersion)
func (b *bibliophileClient) GetCrossMarginAccountData(trader common.Address, mode uint8) (*big.Int, *big.Int, *big.Int, *big.Int) {
output := getCrossMarginAccountData(b.accessibleState.GetStateDB(), &trader, mode)
return output.NotionalPosition, output.RequiredMargin, output.UnrealizedPnl, output.PendingFunding
}

Expand All @@ -238,8 +238,8 @@ func (b *bibliophileClient) GetTraderDataForMarket(trader common.Address, market
return output.IsIsolated, output.NotionalPosition, output.UnrealizedPnl, output.RequiredMargin, output.PendingFunding
}

func (b *bibliophileClient) GetRequiredMargin(baseAsset *big.Int, price *big.Int, marketId int64, trader *common.Address) *big.Int {
return getRequiredMargin(b.accessibleState.GetStateDB(), baseAsset, price, marketId, trader)
func (b *bibliophileClient) GetTraderMarginFraction(market common.Address, trader *common.Address) *big.Int {
return getTraderMarginFraction(b.accessibleState.GetStateDB(), market, trader)
}

func (b *bibliophileClient) HasReferrer(trader common.Address) bool {
Expand Down
36 changes: 18 additions & 18 deletions precompile/contracts/bibliophile/client_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion precompile/contracts/juror/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ func createJurorPrecompile() contract.StatefulPrecompiledContract {
"validateOrdersAndDetermineFillPrice": validateOrdersAndDetermineFillPrice,
"validatePlaceIOCOrder": validatePlaceIOCOrder,
"validatePlaceLimitOrder": validatePlaceLimitOrder,
// @todo add getRequiredMargin
}

for name, function := range abiFunctionMap {
Expand Down
Loading

0 comments on commit 3e524b7

Please sign in to comment.