mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 21:54:30 +00:00
165 lines
8.5 KiB
Go
165 lines
8.5 KiB
Go
package tradingstate
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"math/big"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/log"
|
|
)
|
|
|
|
const DefaultFeeRate = 10 // 10 / XDCXBaseFee = 10 / 10000 = 0.1%
|
|
var ErrQuantityTradeTooSmall = errors.New("quantity trade too small")
|
|
|
|
type TradeResult struct {
|
|
Fee *big.Int
|
|
InToken common.Address
|
|
InTotal *big.Int
|
|
OutToken common.Address
|
|
OutTotal *big.Int
|
|
}
|
|
type SettleBalance struct {
|
|
Taker TradeResult
|
|
Maker TradeResult
|
|
}
|
|
|
|
func (settleBalance *SettleBalance) String() string {
|
|
jsonData, _ := json.Marshal(settleBalance)
|
|
return string(jsonData)
|
|
}
|
|
|
|
func GetSettleBalance(quotePrice *big.Int, takerSide string, takerFeeRate *big.Int, baseToken, quoteToken common.Address, makerPrice *big.Int, makerFeeRate *big.Int, baseTokenDecimal *big.Int, quoteTokenDecimal *big.Int, quantityToTrade *big.Int) (*SettleBalance, error) {
|
|
log.Debug("GetSettleBalance", "takerSide", takerSide, "takerFeeRate", takerFeeRate, "baseToken", baseToken, "quoteToken", quoteToken, "makerPrice", makerPrice, "makerFeeRate", makerFeeRate, "baseTokenDecimal", baseTokenDecimal, "quantityToTrade", quantityToTrade, "quotePrice", quotePrice)
|
|
var result *SettleBalance
|
|
//result = map[common.Address]map[string]interface{}{}
|
|
|
|
// quoteTokenQuantity = quantityToTrade * makerPrice / baseTokenDecimal
|
|
quoteTokenQuantity := new(big.Int).Mul(quantityToTrade, makerPrice)
|
|
quoteTokenQuantity = new(big.Int).Div(quoteTokenQuantity, baseTokenDecimal)
|
|
|
|
makerFee := new(big.Int).Mul(quoteTokenQuantity, makerFeeRate)
|
|
makerFee = new(big.Int).Div(makerFee, common.XDCXBaseFee)
|
|
takerFee := new(big.Int).Mul(quoteTokenQuantity, takerFeeRate)
|
|
takerFee = new(big.Int).Div(takerFee, common.XDCXBaseFee)
|
|
|
|
// use the defaultFee to validate small orders
|
|
defaultFee := new(big.Int).Mul(quoteTokenQuantity, new(big.Int).SetUint64(DefaultFeeRate))
|
|
defaultFee = new(big.Int).Div(defaultFee, common.XDCXBaseFee)
|
|
|
|
if takerSide == Bid {
|
|
if quoteTokenQuantity.Cmp(makerFee) <= 0 || quoteTokenQuantity.Cmp(defaultFee) <= 0 {
|
|
log.Debug("quantity trade too small", "quoteTokenQuantity", quoteTokenQuantity, "makerFee", makerFee, "defaultFee", defaultFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
if quoteToken != common.XDCNativeAddressBinary && quotePrice != nil && quotePrice.Sign() > 0 {
|
|
// defaultFeeInXDC
|
|
defaultFeeInXDC := new(big.Int).Mul(defaultFee, quotePrice)
|
|
defaultFeeInXDC = new(big.Int).Div(defaultFeeInXDC, quoteTokenDecimal)
|
|
|
|
exMakerReceivedFee := new(big.Int).Mul(makerFee, quotePrice)
|
|
exMakerReceivedFee = new(big.Int).Div(exMakerReceivedFee, quoteTokenDecimal)
|
|
if (exMakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exMakerReceivedFee.Sign() > 0) || defaultFeeInXDC.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("makerFee too small", "quoteTokenQuantity", quoteTokenQuantity, "makerFee", makerFee, "exMakerReceivedFee", exMakerReceivedFee, "quotePrice", quotePrice, "defaultFeeInXDC", defaultFeeInXDC)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
exTakerReceivedFee := new(big.Int).Mul(takerFee, quotePrice)
|
|
exTakerReceivedFee = new(big.Int).Div(exTakerReceivedFee, quoteTokenDecimal)
|
|
if (exTakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exTakerReceivedFee.Sign() > 0) || defaultFeeInXDC.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("takerFee too small", "quoteTokenQuantity", quoteTokenQuantity, "takerFee", takerFee, "exTakerReceivedFee", exTakerReceivedFee, "quotePrice", quotePrice, "defaultFeeInXDC", defaultFeeInXDC)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
} else if quoteToken == common.XDCNativeAddressBinary {
|
|
exMakerReceivedFee := makerFee
|
|
if (exMakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exMakerReceivedFee.Sign() > 0) || defaultFee.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("makerFee too small", "quantityToTrade", quantityToTrade, "makerFee", makerFee, "exMakerReceivedFee", exMakerReceivedFee, "makerFeeRate", makerFeeRate, "defaultFee", defaultFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
exTakerReceivedFee := takerFee
|
|
if (exTakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exTakerReceivedFee.Sign() > 0) || defaultFee.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("takerFee too small", "quantityToTrade", quantityToTrade, "takerFee", takerFee, "exTakerReceivedFee", exTakerReceivedFee, "takerFeeRate", takerFeeRate, "defaultFee", defaultFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
}
|
|
inTotal := new(big.Int).Sub(quoteTokenQuantity, makerFee)
|
|
//takerOutTotal= quoteTokenQuantity + takerFee = quantityToTrade*maker.Price/baseTokenDecimal + quantityToTrade*maker.Price/baseTokenDecimal * takerFeeRate/baseFee
|
|
// = quantityToTrade * maker.Price/baseTokenDecimal ( 1 + takerFeeRate/baseFee)
|
|
// = quantityToTrade * maker.Price * (baseFee + takerFeeRate ) / ( baseTokenDecimal * baseFee)
|
|
takerOutTotal := new(big.Int).Add(quoteTokenQuantity, takerFee)
|
|
|
|
result = &SettleBalance{
|
|
Taker: TradeResult{
|
|
Fee: takerFee,
|
|
InToken: baseToken,
|
|
InTotal: quantityToTrade,
|
|
OutToken: quoteToken,
|
|
OutTotal: takerOutTotal,
|
|
},
|
|
Maker: TradeResult{
|
|
Fee: makerFee,
|
|
InToken: quoteToken,
|
|
InTotal: inTotal,
|
|
OutToken: baseToken,
|
|
OutTotal: quantityToTrade,
|
|
},
|
|
}
|
|
} else {
|
|
if quoteTokenQuantity.Cmp(takerFee) <= 0 || quoteTokenQuantity.Cmp(defaultFee) <= 0 {
|
|
log.Debug("quantity trade too small", "quoteTokenQuantity", quoteTokenQuantity, "takerFee", takerFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
if quoteToken != common.XDCNativeAddressBinary && quotePrice != nil && quotePrice.Sign() > 0 {
|
|
// defaultFeeInXDC
|
|
defaultFeeInXDC := new(big.Int).Mul(defaultFee, quotePrice)
|
|
defaultFeeInXDC = new(big.Int).Div(defaultFeeInXDC, quoteTokenDecimal)
|
|
|
|
exMakerReceivedFee := new(big.Int).Mul(makerFee, quotePrice)
|
|
exMakerReceivedFee = new(big.Int).Div(exMakerReceivedFee, quoteTokenDecimal)
|
|
log.Debug("exMakerReceivedFee", "quoteTokenQuantity", quoteTokenQuantity, "makerFee", makerFee, "exMakerReceivedFee", exMakerReceivedFee, "quotePrice", quotePrice)
|
|
if (exMakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exMakerReceivedFee.Sign() > 0) || defaultFeeInXDC.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("makerFee too small", "quoteTokenQuantity", quoteTokenQuantity, "makerFee", makerFee, "exMakerReceivedFee", exMakerReceivedFee, "quotePrice", quotePrice, "defaultMakerFeeInXDC", defaultFeeInXDC)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
exTakerReceivedFee := new(big.Int).Mul(takerFee, quotePrice)
|
|
exTakerReceivedFee = new(big.Int).Div(exTakerReceivedFee, quoteTokenDecimal)
|
|
if (exTakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exTakerReceivedFee.Sign() > 0) || defaultFeeInXDC.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("takerFee too small", "quoteTokenQuantity", quoteTokenQuantity, "takerFee", takerFee, "exTakerReceivedFee", exTakerReceivedFee, "quotePrice", quotePrice, "defaultFeeInXDC", defaultFeeInXDC)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
} else if quoteToken == common.XDCNativeAddressBinary {
|
|
exMakerReceivedFee := makerFee
|
|
if (exMakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exMakerReceivedFee.Sign() > 0) || defaultFee.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("makerFee too small", "quantityToTrade", quantityToTrade, "makerFee", makerFee, "exMakerReceivedFee", exMakerReceivedFee, "makerFeeRate", makerFeeRate, "defaultFee", defaultFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
exTakerReceivedFee := takerFee
|
|
if (exTakerReceivedFee.Cmp(common.RelayerFee) <= 0 && exTakerReceivedFee.Sign() > 0) || defaultFee.Cmp(common.RelayerFee) <= 0 {
|
|
log.Debug("takerFee too small", "quantityToTrade", quantityToTrade, "takerFee", takerFee, "exTakerReceivedFee", exTakerReceivedFee, "takerFeeRate", takerFeeRate, "defaultFee", defaultFee)
|
|
return result, ErrQuantityTradeTooSmall
|
|
}
|
|
}
|
|
inTotal := new(big.Int).Sub(quoteTokenQuantity, takerFee)
|
|
// makerOutTotal = quoteTokenQuantity + makerFee = quantityToTrade * makerPrice / baseTokenDecimal + quantityToTrade * makerPrice / baseTokenDecimal * makerFeeRate / baseFee
|
|
// = quantityToTrade * makerPrice / baseTokenDecimal * (1+makerFeeRate / baseFee)
|
|
// = quantityToTrade * makerPrice * (baseFee + makerFeeRate) / ( baseTokenDecimal * baseFee )
|
|
makerOutTotal := new(big.Int).Add(quoteTokenQuantity, makerFee)
|
|
// Fee
|
|
result = &SettleBalance{
|
|
Taker: TradeResult{
|
|
Fee: takerFee,
|
|
InToken: quoteToken,
|
|
InTotal: inTotal,
|
|
OutToken: baseToken,
|
|
OutTotal: quantityToTrade,
|
|
},
|
|
Maker: TradeResult{
|
|
Fee: makerFee,
|
|
InToken: baseToken,
|
|
InTotal: quantityToTrade,
|
|
OutToken: quoteToken,
|
|
OutTotal: makerOutTotal,
|
|
},
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|