Skip to content

Commit

Permalink
Add next function at decode package
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisngyn committed Aug 16, 2024
1 parent 67098cc commit 4e93168
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 52 deletions.
17 changes: 17 additions & 0 deletions pkg/oneinch/decode/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package decode
import (
"errors"
"fmt"
"math/big"
)

var ErrInvalidDataLength = errors.New("invalid data length")
Expand All @@ -13,3 +14,19 @@ func ValidateDataLength(data []byte, size int) error {
}
return nil
}

func Next(data []byte, size int) ([]byte, []byte, error) {
if err := ValidateDataLength(data, size); err != nil {
return nil, nil, err
}
return data[:size], data[size:], nil
}

func NextInt64(data []byte, size int) (int64, []byte, error) {
d, remainingData, err := Next(data, size)
if err != nil {
return 0, nil, err
}

return new(big.Int).SetBytes(d).Int64(), remainingData, nil
}
31 changes: 18 additions & 13 deletions pkg/oneinch/fusionorder/auction_details.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,18 @@ type AuctionGasCostInfo struct {
// nolint: gomnd
func DecodeAuctionDetails(hexData []byte) (AuctionDetails, error) {
const firstLength = 17
if err := decode.ValidateDataLength(hexData, firstLength); err != nil {
return AuctionDetails{}, fmt.Errorf("validate out of range for auction details: %w", err)
offsetData, remainingData, err := decode.Next(hexData, firstLength)
if err != nil {
return AuctionDetails{}, fmt.Errorf("next offset: %w", err)
}
gasBumpEstimate := new(big.Int).SetBytes(hexData[:3]).Int64()
gasPriceEstimate := new(big.Int).SetBytes(hexData[3:7]).Int64()
startTime := new(big.Int).SetBytes(hexData[7:11]).Int64()
duration := new(big.Int).SetBytes(hexData[11:14]).Int64()
initialRateBump := new(big.Int).SetBytes(hexData[14:17]).Int64()

points, err := decodeAuctionPoints(hexData[firstLength:])
gasBumpEstimate := new(big.Int).SetBytes(offsetData[:3]).Int64()
gasPriceEstimate := new(big.Int).SetBytes(offsetData[3:7]).Int64()
startTime := new(big.Int).SetBytes(offsetData[7:11]).Int64()
duration := new(big.Int).SetBytes(offsetData[11:14]).Int64()
initialRateBump := new(big.Int).SetBytes(offsetData[14:17]).Int64()

points, err := decodeAuctionPoints(remainingData)
if err != nil {
return AuctionDetails{}, fmt.Errorf("decode auction points: %w", err)
}
Expand All @@ -120,16 +122,19 @@ func decodeAuctionPoints(data []byte) ([]AuctionPoint, error) {
points := make([]AuctionPoint, 0)
for len(data) > 0 {
const pointLength = 5
if err := decode.ValidateDataLength(data, pointLength); err != nil {
return nil, fmt.Errorf("validate out of range for auction point: %w", err)
pointData, remainingData, err := decode.Next(data, pointLength)
if err != nil {
return nil, fmt.Errorf("next auction point: %w", err)
}
coefficient := new(big.Int).SetBytes(data[:3]).Int64()
delay := new(big.Int).SetBytes(data[3:5]).Int64()

coefficient := new(big.Int).SetBytes(pointData[:3]).Int64()
delay := new(big.Int).SetBytes(pointData[3:5]).Int64()
points = append(points, AuctionPoint{
Coefficient: coefficient,
Delay: delay,
})
data = data[pointLength:]

data = remainingData
}
return points, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package fusionorder
import (
"bytes"
"fmt"
"math/big"

"github.com/KyberNetwork/tradinglib/pkg/oneinch/decode"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -32,85 +31,109 @@ func resolversCount(flags byte) byte {
return flags >> whitelistShift
}

// DecodeSettlementPostInteractionData decodes SettlementPostInteractionData from bytes
// nolint: gomnd
func DecodeSettlementPostInteractionData(data []byte) (SettlementPostInteractionData, error) {
// must have at least 1 byte for flags
// nolint: gomnd
if err := decode.ValidateDataLength(data, 1); err != nil {
return SettlementPostInteractionData{}, err
}

flags := data[len(data)-1]

bankFee := big.NewInt(0)
var bankFee int64
var integratorFee IntegratorFee
var customReceiver common.Address
var resolvingStartTime int64
var err error

if resolverFeeEnabled(flags) {
const lengthBankFee = 4
if err := decode.ValidateDataLength(data, lengthBankFee); err != nil {
bankFee, data, err = decode.NextInt64(data, lengthBankFee)
if err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get bank fee: %w", err)
}
bankFee.SetBytes(data[:lengthBankFee])
data = data[lengthBankFee:]
}

if integratorFeeEnabled(flags) {
const lengthIntegratorFee = 2 + common.AddressLength
if err := decode.ValidateDataLength(data, lengthIntegratorFee); err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get integrator fee: %w", err)
}
integratorFeeRatio := new(big.Int).SetBytes(data[:2]).Int64()
integratorAddress := common.BytesToAddress(data[2:lengthIntegratorFee])
integratorFee = IntegratorFee{
Ratio: integratorFeeRatio,
Receiver: integratorAddress,
}

data = data[lengthIntegratorFee:]

if hasCustomReceiver(flags) {
if err := decode.ValidateDataLength(data, common.AddressLength); err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get custom receiver: %w", err)
}
customReceiver = common.BytesToAddress(data[:common.AddressLength])
data = data[common.AddressLength:]
}
integratorFee, customReceiver, data, err = decodeIntegratorFee(flags, data)
if err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get integrator fee: %w", err)
}

resolvingStartTime := new(big.Int).SetBytes(data[:4])
data = data[4:]
resolvingStartTime, data, err = decode.NextInt64(data, 4)
if err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get resolving start time: %w", err)
}

whitelistCount := resolversCount(flags)
whitelist := make([]WhitelistItem, 0, whitelistCount)

for i := byte(0); i < whitelistCount; i++ {
const lengthWhitelistItem = addressHalfLength + 2
if err := decode.ValidateDataLength(data, lengthWhitelistItem); err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get whitelist item: %w", err)
var addressHalfBytes []byte
addressHalfBytes, data, err = decode.Next(data, addressHalfLength)
if err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get whitelist item address half: %w", err)
}

var address AddressHalf
copy(address[:], data[:addressHalfLength])
data = data[addressHalfLength:]
copy(address[:], addressHalfBytes)

delay := new(big.Int).SetBytes(data[:2])
data = data[2:]
var delay int64
delay, data, err = decode.NextInt64(data, 2)
if err != nil {
return SettlementPostInteractionData{}, fmt.Errorf("get whitelist item delay: %w", err)
}

whitelist = append(whitelist, WhitelistItem{
AddressHalf: address,
Delay: delay.Int64(),
Delay: delay,
})
}

return SettlementPostInteractionData{
Whitelist: whitelist,
IntegratorFee: integratorFee,
BankFee: bankFee.Int64(),
ResolvingStartTime: resolvingStartTime.Int64(),
BankFee: bankFee,
ResolvingStartTime: resolvingStartTime,
CustomReceiver: customReceiver,
}, nil
}

func decodeIntegratorFee(
flags byte, data []byte,
) (integratorFee IntegratorFee, customReceiver common.Address, remainingData []byte, err error) {
if !integratorFeeEnabled(flags) {
return integratorFee, customReceiver, data, nil
}

var integratorFeeRatio int64
integratorFeeRatio, data, err = decode.NextInt64(data, 2) // nolint: gomnd
if err != nil {
return integratorFee, customReceiver, data, fmt.Errorf("get integrator fee ratio: %w", err)
}
var integratorAddress []byte
integratorAddress, data, err = decode.Next(data, common.AddressLength)
if err != nil {
return integratorFee, customReceiver, data, fmt.Errorf("get integrator fee address: %w", err)
}

integratorFee = IntegratorFee{
Ratio: integratorFeeRatio,
Receiver: common.BytesToAddress(integratorAddress),
}

if hasCustomReceiver(flags) {
var customReceiverBytes []byte
customReceiverBytes, data, err = decode.Next(data, common.AddressLength)
if err != nil {
return integratorFee, customReceiver, data, fmt.Errorf("get custom receiver: %w", err)
}
customReceiver = common.BytesToAddress(customReceiverBytes)
}

return integratorFee, customReceiver, data, nil
}

// Encode encodes SettlementPostInteractionData to bytes
// nolint: gomnd
func (s SettlementPostInteractionData) Encode() []byte {
Expand Down

0 comments on commit 4e93168

Please sign in to comment.