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

Implement encode/decode 1inch extension #75

Merged
merged 26 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
944e670
Add encode/decode 1inch extension
chrisngyn Aug 14, 2024
2510fc7
Fix lint
chrisngyn Aug 14, 2024
b22fe84
Add interaction
chrisngyn Aug 14, 2024
b696b9a
Implement interaction
chrisngyn Aug 15, 2024
dbaf2c7
Implement encode/decode auction details
chrisngyn Aug 15, 2024
13856ba
Implement encode/decode settlement post interaction data
chrisngyn Aug 15, 2024
2e6c529
Add fusion extension decode
chrisngyn Aug 16, 2024
fe2282c
Convert auction details to use primitive types
chrisngyn Aug 16, 2024
6af0e34
Convert settlement post interaction data to use primitive types
chrisngyn Aug 16, 2024
cef15ad
Replace extension fields by byte arrays
chrisngyn Aug 16, 2024
abbc9a8
Convert string to []byte
chrisngyn Aug 16, 2024
769b990
Sink some packages
chrisngyn Aug 16, 2024
80a4d48
Shorten function encode
chrisngyn Aug 16, 2024
8879836
Make lint happy
chrisngyn Aug 16, 2024
18a5b09
Remove trim0x function
chrisngyn Aug 16, 2024
e1921b0
Remove ZX global constant
chrisngyn Aug 16, 2024
4f62e68
Use math.PaddedBigBytes instead
chrisngyn Aug 16, 2024
d3b99ca
Check data length before get it from bytes
chrisngyn Aug 16, 2024
c2cc714
Add next function at decode package
chrisngyn Aug 16, 2024
4ea1f6b
Implement bytes iterator
chrisngyn Aug 19, 2024
88cb698
Remove completely zx
chrisngyn Aug 19, 2024
1fcc00b
Remove unused assert in test
chrisngyn Aug 19, 2024
d520732
Add check less than 0 when create auction details
chrisngyn Aug 19, 2024
61cd33e
Remove big package in bytes iterator
chrisngyn Aug 19, 2024
0bcd9a9
Add assert for some tests
chrisngyn Aug 19, 2024
e6fbfe5
Return offset is a common.Hash
chrisngyn Aug 19, 2024
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
41 changes: 16 additions & 25 deletions pkg/oneinch/auction/calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"math/big"

"github.com/KyberNetwork/tradinglib/pkg/oneinch/fusionorder"
"github.com/KyberNetwork/tradinglib/pkg/oneinch/fusionutils"
)

const (
Expand All @@ -25,36 +24,27 @@ type Calculator struct {
}

func NewCalculator(
startTime *big.Int,
duration *big.Int,
initialRateBump *big.Int,
startTime int64,
duration int64,
initialRateBump int64,
points []fusionorder.AuctionPoint,
takerFeeRatio *big.Int,
takerFeeRatio int64,
gasCost fusionorder.AuctionGasCostInfo,
) Calculator {
if gasCost.GasBumpEstimate == nil {
gasCost.GasBumpEstimate = big.NewInt(0)
}
if gasCost.GasPriceEstimate == nil {
gasCost.GasPriceEstimate = big.NewInt(0)
}
return Calculator{
startTime: startTime,
duration: duration,
initialRateBump: initialRateBump,
startTime: big.NewInt(startTime),
duration: big.NewInt(duration),
initialRateBump: big.NewInt(initialRateBump),
points: points,
takerFeeRatio: takerFeeRatio,
takerFeeRatio: big.NewInt(takerFeeRatio),
gasCost: gasCost,
}
}

func NewCalculatorFromAuctionData(
takerFeeRatio *big.Int,
takerFeeRatio int64,
auctionDetails fusionorder.AuctionDetails,
) Calculator {
if takerFeeRatio == nil {
takerFeeRatio = big.NewInt(0)
}
return NewCalculator(
auctionDetails.StartTime,
auctionDetails.Duration,
Expand Down Expand Up @@ -82,23 +72,24 @@ func (c Calculator) CalcRateBump(time, blockBaseFee *big.Int) int64 {
}

func (c Calculator) getGasPriceBump(blockBaseFee *big.Int) *big.Int {
zeroBigInt := new(big.Int)
zeroBigInt := big.NewInt(0)
if zeroBigInt.Cmp(blockBaseFee) == 0 {
return zeroBigInt
}
if zeroBigInt.Cmp(c.gasCost.GasPriceEstimate) == 0 {
if c.gasCost.GasPriceEstimate == 0 {
return zeroBigInt
}
if zeroBigInt.Cmp(c.gasCost.GasBumpEstimate) == 0 {
if c.gasCost.GasBumpEstimate == 0 {
return zeroBigInt
}

return new(big.Int).Div(
new(big.Int).Div(
new(big.Int).Mul(
c.gasCost.GasBumpEstimate, blockBaseFee,
big.NewInt(c.gasCost.GasBumpEstimate), blockBaseFee,
),
c.gasCost.GasPriceEstimate),
big.NewInt(c.gasCost.GasPriceEstimate),
),
big.NewInt(GasPriceBase),
)
}
Expand Down Expand Up @@ -171,7 +162,7 @@ func calcAuctionTakingAmount(takingAmount *big.Int, rate int64, takerFeeRatio *b
return auctionTakingAmount
}

return fusionutils.AddRatioToAmount(auctionTakingAmount, takerFeeRatio)
return fusionorder.AddRatioToAmount(auctionTakingAmount, takerFeeRatio)
}

func CalcInitialRateBump(startAmount *big.Int, endAmount *big.Int) int64 {
Expand Down
35 changes: 17 additions & 18 deletions pkg/oneinch/auction/calculator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,21 @@ import (
"github.com/KyberNetwork/tradinglib/pkg/convert"
"github.com/KyberNetwork/tradinglib/pkg/oneinch/auction"
"github.com/KyberNetwork/tradinglib/pkg/oneinch/fusionorder"
"github.com/KyberNetwork/tradinglib/pkg/oneinch/fusionutils"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAuctionCalculator(t *testing.T) {
t.Run("should be created successfully from suffix and salt", func(t *testing.T) {
auctionStartTime := big.NewInt(1708448252)
auctionStartTime := int64(1708448252)
postInteraction, err := fusionorder.NewSettlementPostInteractionDataFromSettlementSuffixData(
fusionorder.SettlementSuffixData{
IntegratorFee: fusionorder.IntegratorFee{
Ratio: fusionutils.BpsToRatioFormat(1),
Ratio: fusionorder.BpsToRatioFormat(1).Int64(),
Receiver: common.BigToAddress(big.NewInt(1)),
},
BankFee: big.NewInt(0),
BankFee: 0,
ResolvingStartTime: auctionStartTime,
Whitelist: []fusionorder.AuctionWhitelistItem{
{
Expand All @@ -36,8 +35,8 @@ func TestAuctionCalculator(t *testing.T) {

actionDetails, err := fusionorder.NewAuctionDetails(
auctionStartTime,
big.NewInt(50_000),
big.NewInt(120),
50_000,
120,
nil,
fusionorder.AuctionGasCostInfo{},
)
Expand All @@ -48,7 +47,7 @@ func TestAuctionCalculator(t *testing.T) {
takingAmount, ok := new(big.Int).SetString("1420000000", 10)
require.True(t, ok)

rate := calculator.CalcRateBump(new(big.Int).Add(auctionStartTime, big.NewInt(60)), big.NewInt(0))
rate := calculator.CalcRateBump(big.NewInt(auctionStartTime+60), big.NewInt(0))
auctionTakingAmount := calculator.CalcAuctionTakingAmount(takingAmount, rate)

assert.Equal(t, int64(25000), rate)
Expand All @@ -57,46 +56,46 @@ func TestAuctionCalculator(t *testing.T) {
}

func TestCalculator_GasBump(t *testing.T) {
now := big.NewInt(time.Now().Unix())
duration := big.NewInt(1800) // 30 minutes
now := time.Now().Unix()
duration := int64(1800) // 30 minutes
takingAmount := parseEther(t, 1)
calculator := auction.NewCalculator(
new(big.Int).Sub(now, big.NewInt(60)),
now-60,
duration,
big.NewInt(1000000),
1000000,
[]fusionorder.AuctionPoint{
{
Delay: 60,
Coefficient: 500000,
},
},
big.NewInt(0),
0,
fusionorder.AuctionGasCostInfo{
GasBumpEstimate: big.NewInt(10000),
GasPriceEstimate: big.NewInt(1000),
GasBumpEstimate: 10_000,
GasPriceEstimate: 1000,
},
)

t.Run("0 gwei = no gas fee", func(t *testing.T) {
bump := calculator.CalcRateBump(now, big.NewInt(0))
bump := calculator.CalcRateBump(big.NewInt(now), big.NewInt(0))
auctionTakingAmount := calculator.CalcAuctionTakingAmount(takingAmount, bump)
assert.Zero(t, auctionTakingAmount.Cmp(parseEther(t, 1.05)))
})

t.Run("0.1 gwei == 0.01% gas fee", func(t *testing.T) {
bump := calculator.CalcRateBump(now, parseUnits(t, 1, 8))
bump := calculator.CalcRateBump(big.NewInt(now), parseUnits(t, 1, 8))
auctionTakingAmount := calculator.CalcAuctionTakingAmount(takingAmount, bump)
assert.Zero(t, auctionTakingAmount.Cmp(parseEther(t, 1.0499)))
})

t.Run("15 gwei == 1.5% gas fee", func(t *testing.T) {
bump := calculator.CalcRateBump(now, parseUnits(t, 15, 9))
bump := calculator.CalcRateBump(big.NewInt(now), parseUnits(t, 15, 9))
auctionTakingAmount := calculator.CalcAuctionTakingAmount(takingAmount, bump)
assert.Zero(t, auctionTakingAmount.Cmp(parseEther(t, 1.035)))
})

t.Run("100 gwei == 10% gas fee", func(t *testing.T) {
bump := calculator.CalcRateBump(now, parseUnits(t, 100, 9))
bump := calculator.CalcRateBump(big.NewInt(now), parseUnits(t, 100, 9))
auctionTakingAmount := calculator.CalcAuctionTakingAmount(takingAmount, bump)
assert.Zero(t, auctionTakingAmount.Cmp(parseEther(t, 1)))
})
Expand Down
80 changes: 80 additions & 0 deletions pkg/oneinch/decode/bytes_iterator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package decode

import (
"encoding/binary"
"errors"
)

var ErrOutOfData = errors.New("out of data")

type BytesIterator struct {
data []byte
}

func NewBytesIterator(data []byte) *BytesIterator {
return &BytesIterator{data: data}
}

func (bi *BytesIterator) RemainingData() []byte {
return bi.data
}

func (bi *BytesIterator) HasMore() bool {
return len(bi.data) > 0
}

func (bi *BytesIterator) NextBytes(length int) ([]byte, error) {
if len(bi.data) < length {
return nil, ErrOutOfData
}

result := bi.data[:length]
bi.data = bi.data[length:]

return result, nil
}

func (bi *BytesIterator) NextUint8() (uint8, error) {
result, err := bi.NextBytes(1) // nolint: gomnd
if err != nil {
return 0, err
}

return result[0], nil
}

func (bi *BytesIterator) NextUint16() (uint16, error) {
result, err := bi.NextBytes(2) // nolint: gomnd
if err != nil {
return 0, err
}

return binary.BigEndian.Uint16(result), nil
}

func (bi *BytesIterator) NextUint24() (uint32, error) {
result, err := bi.NextBytes(3) // nolint: gomnd
if err != nil {
return 0, err
}

return binary.BigEndian.Uint32(append([]byte{0}, result...)), nil
}

func (bi *BytesIterator) NextUint32() (uint32, error) {
result, err := bi.NextBytes(4) // nolint: gomnd
if err != nil {
return 0, err
}

return binary.BigEndian.Uint32(result), nil
}

func (bi *BytesIterator) NextUint64() (uint64, error) {
result, err := bi.NextBytes(8) // nolint: gomnd
if err != nil {
return 0, err
}

return binary.BigEndian.Uint64(result), nil
}
19 changes: 19 additions & 0 deletions pkg/oneinch/fusionorder/address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fusionorder

import "github.com/ethereum/go-ethereum/common"

const (
addressHalfLength = common.AddressLength / 2
)

type AddressHalf [addressHalfLength]byte

func HalfAddressFromAddress(a common.Address) AddressHalf {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly we never modify an address, I think get a slice of bytes will save some allocation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because AddressHalf is a static slice of bytes, same as common.Address. So I decided still keep it.

var addressHalf AddressHalf
copy(addressHalf[:], a.Bytes()[common.AddressLength-addressHalfLength:]) // take the last 10 bytes
return addressHalf
}

func AddressFromFirstBytes(s []byte) common.Address {
return common.BytesToAddress(s[:common.AddressLength])
}
Loading
Loading