Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precompile updates #113

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions contracts/contracts/hubble-v2/interfaces/IJuror.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ pragma solidity ^0.8.0;
import { IOrderHandler } from "./IOrderHandler.sol";

interface IJuror {
enum BadElement { Order0, Order1, Generic }
enum BadElement { Order0, Order1, Generic, NoError }

// Order Matching
function validateOrdersAndDetermineFillPrice(
bytes[2] calldata data,
int256 fillAmount
) external
view
returns(string memory err, BadElement reason, IOrderHandler.MatchingValidationRes memory res);
returns(string memory err, BadElement element, IOrderHandler.MatchingValidationRes memory res);

function validateLiquidationOrderAndDetermineFillPrice(bytes calldata data, uint256 liquidationAmount)
external
view
returns(string memory err, IOrderHandler.LiquidationMatchingValidationRes memory res);
returns(string memory err, BadElement element, IOrderHandler.LiquidationMatchingValidationRes memory res);

// Limit Orders
function validatePlaceLimitOrder(ILimitOrderBook.Order calldata order, address sender)
Expand Down
16 changes: 16 additions & 0 deletions plugin/evm/orderbook/hubbleutils/hubble_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ var (
ONE_E_18 = big.NewInt(1e18)
)

func Add1e6(a *big.Int) *big.Int {
return Add(a, ONE_E_6)
}

func Mul1e6(a *big.Int) *big.Int {
return Mul(a, ONE_E_6)
}
Expand Down Expand Up @@ -41,3 +45,15 @@ func Mul(a, b *big.Int) *big.Int {
func Div(a, b *big.Int) *big.Int {
return new(big.Int).Div(a, b)
}

func Abs(a *big.Int) *big.Int {
return new(big.Int).Abs(a)
}

func RoundOff(a, b *big.Int) *big.Int {
return Mul(Div(a, b), b)
}

func Mod(a, b *big.Int) *big.Int {
return new(big.Int).Mod(a, b)
}
52 changes: 33 additions & 19 deletions precompile/contracts/bibliophile/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,23 @@ import (
)

const (
VAR_POSITIONS_SLOT int64 = 5
VAR_CUMULATIVE_PREMIUM_FRACTION int64 = 6
MAX_ORACLE_SPREAD_RATIO_SLOT int64 = 7
MAX_LIQUIDATION_RATIO_SLOT int64 = 8
MIN_SIZE_REQUIREMENT_SLOT int64 = 9
ORACLE_SLOT int64 = 10
UNDERLYING_ASSET_SLOT int64 = 11
MAX_LIQUIDATION_PRICE_SPREAD int64 = 17
RED_STONE_ADAPTER_SLOT int64 = 21
RED_STONE_FEED_ID_SLOT int64 = 22
IMPACT_MARGIN_NOTIONAL_SLOT int64 = 27
LAST_TRADE_PRICE_SLOT int64 = 28
BIDS_SLOT int64 = 29
ASKS_SLOT int64 = 30
BIDS_HEAD_SLOT int64 = 31
ASKS_HEAD_SLOT int64 = 32
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
ORACLE_SLOT int64 = 6
UNDERLYING_ASSET_SLOT int64 = 7
MAX_LIQUIDATION_PRICE_SPREAD int64 = 12
RED_STONE_ADAPTER_SLOT int64 = 16
RED_STONE_FEED_ID_SLOT int64 = 17
IMPACT_MARGIN_NOTIONAL_SLOT int64 = 22
LAST_TRADE_PRICE_SLOT int64 = 23
BIDS_SLOT int64 = 24
ASKS_SLOT int64 = 25
BIDS_HEAD_SLOT int64 = 24
ASKS_HEAD_SLOT int64 = 25
MULTIPLIER_SLOT int64 = 30
)

const (
Expand All @@ -51,19 +52,28 @@ func GetCumulativePremiumFraction(stateDB contract.StateDB, market common.Addres

// GetMaxOraclePriceSpread returns the maxOracleSpreadRatio for a given market
func GetMaxOraclePriceSpread(stateDB contract.StateDB, marketID int64) *big.Int {
market := getMarketAddressFromMarketID(marketID, stateDB)
return getMaxOraclePriceSpread(stateDB, getMarketAddressFromMarketID(marketID, stateDB))
}

func getMaxOraclePriceSpread(stateDB contract.StateDB, market common.Address) *big.Int {
return fromTwosComplement(stateDB.GetState(market, common.BigToHash(big.NewInt(MAX_ORACLE_SPREAD_RATIO_SLOT))).Bytes())
}

// GetMaxLiquidationPriceSpread returns the maxOracleSpreadRatio for a given market
func GetMaxLiquidationPriceSpread(stateDB contract.StateDB, marketID int64) *big.Int {
market := getMarketAddressFromMarketID(marketID, stateDB)
return getMaxLiquidationPriceSpread(stateDB, getMarketAddressFromMarketID(marketID, stateDB))
}

func getMaxLiquidationPriceSpread(stateDB contract.StateDB, market common.Address) *big.Int {
return fromTwosComplement(stateDB.GetState(market, common.BigToHash(big.NewInt(MAX_LIQUIDATION_PRICE_SPREAD))).Bytes())
}

// GetMaxLiquidationRatio returns the maxLiquidationPriceSpread for a given market
func GetMaxLiquidationRatio(stateDB contract.StateDB, marketID int64) *big.Int {
market := getMarketAddressFromMarketID(marketID, stateDB)
return getMaxLiquidationRatio(stateDB, getMarketAddressFromMarketID(marketID, stateDB))
}

func getMaxLiquidationRatio(stateDB contract.StateDB, market common.Address) *big.Int {
return fromTwosComplement(stateDB.GetState(market, common.BigToHash(big.NewInt(MAX_LIQUIDATION_RATIO_SLOT))).Bytes())
}

Expand All @@ -73,6 +83,10 @@ func GetMinSizeRequirement(stateDB contract.StateDB, marketID int64) *big.Int {
return fromTwosComplement(stateDB.GetState(market, common.BigToHash(big.NewInt(MIN_SIZE_REQUIREMENT_SLOT))).Bytes())
}

func getMultiplier(stateDB contract.StateDB, market common.Address) *big.Int {
return stateDB.GetState(market, common.BigToHash(big.NewInt(MULTIPLIER_SLOT))).Big()
}

func getOracleAddress(stateDB contract.StateDB, market common.Address) common.Address {
return common.BytesToAddress(stateDB.GetState(market, common.BigToHash(big.NewInt(ORACLE_SLOT))).Bytes())
}
Expand Down
6 changes: 6 additions & 0 deletions precompile/contracts/bibliophile/clearing_house.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
MIN_ALLOWABLE_MARGIN_SLOT int64 = 2
TAKER_FEE_SLOT int64 = 3
AMMS_SLOT int64 = 12
REFERRAL_SLOT int64 = 13
)

type MarginMode uint8
Expand Down Expand Up @@ -134,3 +135,8 @@ func getMarketAddressFromMarketID(marketID int64, stateDB contract.StateDB) comm
amm := stateDB.GetState(common.HexToAddress(CLEARING_HOUSE_GENESIS_ADDRESS), common.BigToHash(new(big.Int).Add(baseStorageSlot, big.NewInt(marketID))))
return common.BytesToAddress(amm.Bytes())
}

func getReferralAddress(stateDB contract.StateDB) common.Address {
referral := stateDB.GetState(common.HexToAddress(CLEARING_HOUSE_GENESIS_ADDRESS), common.BigToHash(big.NewInt(REFERRAL_SLOT)))
return common.BytesToAddress(referral.Bytes())
}
10 changes: 10 additions & 0 deletions precompile/contracts/bibliophile/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ type BibliophileClient interface {
GetImpactMarginNotional(ammAddress common.Address) *big.Int
GetBidsHead(market common.Address) *big.Int
GetAsksHead(market common.Address) *big.Int
GetPriceMultiplier(market common.Address) *big.Int
GetUpperAndLowerBoundForMarket(marketId int64) (*big.Int, *big.Int)
GetAcceptableBoundsForLiquidation(marketId int64) (*big.Int, *big.Int)

GetAccessibleState() contract.AccessibleState
GetNotionalPositionAndMargin(trader common.Address, includeFundingPayments bool, mode uint8) (*big.Int, *big.Int)
HasReferrer(trader common.Address) bool
}

// Define a structure that will implement the Bibliophile interface
Expand Down Expand Up @@ -159,6 +161,10 @@ func (b *bibliophileClient) GetAsksHead(market common.Address) *big.Int {
return getAsksHead(b.accessibleState.GetStateDB(), market)
}

func (b *bibliophileClient) GetPriceMultiplier(market common.Address) *big.Int {
return getMultiplier(b.accessibleState.GetStateDB(), market)
}

func (b *bibliophileClient) GetLongOpenOrdersAmount(trader common.Address, ammIndex *big.Int) *big.Int {
return getLongOpenOrdersAmount(b.accessibleState.GetStateDB(), trader, ammIndex)
}
Expand All @@ -179,3 +185,7 @@ func (b *bibliophileClient) GetNotionalPositionAndMargin(trader common.Address,
output := getNotionalPositionAndMargin(b.accessibleState.GetStateDB(), &GetNotionalPositionAndMarginInput{Trader: trader, IncludeFundingPayments: includeFundingPayments, Mode: mode})
return output.NotionalPosition, output.Margin
}

func (b *bibliophileClient) HasReferrer(trader common.Address) bool {
return hasReferrer(b.accessibleState.GetStateDB(), trader)
}
28 changes: 28 additions & 0 deletions precompile/contracts/bibliophile/client_mock.go

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

16 changes: 7 additions & 9 deletions precompile/contracts/bibliophile/orderbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,20 @@ func IsValidator(stateDB contract.StateDB, senderOrSigner common.Address) bool {
// Helper functions

func GetAcceptableBounds(stateDB contract.StateDB, marketID int64) (upperBound, lowerBound *big.Int) {
spreadLimit := GetMaxOraclePriceSpread(stateDB, marketID)
oraclePrice := getUnderlyingPriceForMarket(stateDB, marketID)
return calculateBounds(spreadLimit, oraclePrice)
market := getMarketAddressFromMarketID(marketID, stateDB)
return calculateBounds(getMaxOraclePriceSpread(stateDB, market), getUnderlyingPrice(stateDB, market), getMultiplier(stateDB, market))
}

func GetAcceptableBoundsForLiquidation(stateDB contract.StateDB, marketID int64) (upperBound, lowerBound *big.Int) {
spreadLimit := GetMaxLiquidationPriceSpread(stateDB, marketID)
oraclePrice := getUnderlyingPriceForMarket(stateDB, marketID)
return calculateBounds(spreadLimit, oraclePrice)
market := getMarketAddressFromMarketID(marketID, stateDB)
return calculateBounds(getMaxLiquidationPriceSpread(stateDB, market), getUnderlyingPrice(stateDB, market), getMultiplier(stateDB, market))
}

func calculateBounds(spreadLimit, oraclePrice *big.Int) (*big.Int, *big.Int) {
upperbound := hu.Div1e6(hu.Mul(oraclePrice, hu.Add(hu.ONE_E_6, spreadLimit)))
func calculateBounds(spreadLimit, oraclePrice, multiplier *big.Int) (*big.Int, *big.Int) {
upperbound := hu.RoundOff(hu.Div1e6(hu.Mul(oraclePrice, hu.Add1e6(spreadLimit))), multiplier)
lowerbound := big.NewInt(0)
if spreadLimit.Cmp(hu.ONE_E_6) == -1 {
lowerbound = hu.Div1e6(hu.Mul(oraclePrice, hu.Sub(hu.ONE_E_6, spreadLimit)))
lowerbound = hu.RoundOff(hu.Div1e6(hu.Mul(oraclePrice, hu.Sub(hu.ONE_E_6, spreadLimit))), multiplier)
}
return upperbound, lowerbound
}
29 changes: 29 additions & 0 deletions precompile/contracts/bibliophile/referral.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package bibliophile

import (
"math/big"

"github.com/ava-labs/subnet-evm/precompile/contract"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

const (
TRADER_TO_REFERRER_SLOT int64 = 3
RESTRICTED_INVITES_SLOT int64 = 6
)

func restrictedInvites(stateDB contract.StateDB, referralContract common.Address) bool {
return stateDB.GetState(referralContract, common.BigToHash(big.NewInt(RESTRICTED_INVITES_SLOT))).Big().Uint64() == 1
}

func traderToReferrer(stateDB contract.StateDB, referralContract, trader common.Address) common.Address {
pos := crypto.Keccak256(append(common.LeftPadBytes(trader.Bytes(), 32), common.LeftPadBytes(big.NewInt(TRADER_TO_REFERRER_SLOT).Bytes(), 32)...))
return common.BytesToAddress(stateDB.GetState(referralContract, common.BytesToHash(pos)).Bytes())
}

func hasReferrer(stateDB contract.StateDB, trader common.Address) bool {
referralContract := getReferralAddress(stateDB)
return !restrictedInvites(stateDB, referralContract) || traderToReferrer(stateDB, referralContract, trader) != common.Address{}
}
Loading