Skip to content

Commit

Permalink
Revert "Convert Gas price in USD (#290)"
Browse files Browse the repository at this point in the history
This reverts commit c7fea63.
  • Loading branch information
makramkd authored Nov 6, 2024
1 parent 733f5d2 commit 590a9fc
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 110 deletions.
64 changes: 5 additions & 59 deletions execute/exectypes/costly_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (

"github.com/smartcontractkit/chainlink-ccip/execute/internal/gas"

"github.com/smartcontractkit/chainlink-common/pkg/types"

"github.com/smartcontractkit/chainlink-ccip/internal/plugintypes"
readerpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader"
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
Expand Down Expand Up @@ -299,10 +297,7 @@ func (c *CCIPMessageFeeUSD18Calculator) MessageFeeUSD18(

messageFees := make(map[cciptypes.Bytes32]plugintypes.USD18)
for _, msg := range messages {
feeUSD18 := new(big.Int).Div(
new(big.Int).Mul(linkPriceUSD.Int, msg.FeeValueJuels.Int),
new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil),
)
feeUSD18 := new(big.Int).Mul(linkPriceUSD.Int, msg.FeeValueJuels.Int)
timestamp, ok := messageTimeStamps[msg.Header.MessageID]
if !ok {
// If a timestamp is missing we can't do fee boosting, but we still record the fee. In the worst case, the
Expand Down Expand Up @@ -339,16 +334,12 @@ type CCIPMessageExecCostUSD18Calculator struct {
estimateProvider gas.EstimateProvider
}

// getFeesUSD18 converts the fee components (ExecutionFee and DataAvailabilityFee) from native token units
// to USD with 18 decimals (USD18).
// MessageExecCostUSD18 returns a map from message ID to the message's estimated execution cost in USD18s.
func (c *CCIPMessageExecCostUSD18Calculator) MessageExecCostUSD18(
ctx context.Context,
messages []cciptypes.Message,
) (map[cciptypes.Bytes32]plugintypes.USD18, error) {
messageExecCosts := make(map[cciptypes.Bytes32]plugintypes.USD18)

// Retrieve the fee components from the destination chain.
// feeComponents.ExecutionFee and feeComponents.DataAvailabilityFee are in native token units.
feeComponents, err := c.ccipReader.GetDestChainFeeComponents(ctx)
if err != nil {
return nil, fmt.Errorf("unable to get fee components: %w", err)
Expand All @@ -359,64 +350,21 @@ func (c *CCIPMessageExecCostUSD18Calculator) MessageExecCostUSD18(
if feeComponents.DataAvailabilityFee == nil {
return nil, fmt.Errorf("missing data availability fee")
}
if len(messages) == 0 {
return messageExecCosts, nil
}

// Calculate execution fee in USD18 by multiplying the execution fee (in native tokens) by the native token price.
// feeComponents.ExecutionFee is in native tokens, nativeTokenPrice is in USD18, so the result is scaled by 1e18.
executionFee, daFee, err := c.getFeesUSD18(ctx, feeComponents, messages[0].Header.DestChainSelector)
if err != nil {
return nil, fmt.Errorf("unable to convert fee components to USD18: %w", err)
}

// Calculate da fee in USD18 by multiplying the data availability fee (in native tokens) by the native token price.
// feeComponents.DataAvailabilityFee is in native tokens, nativeTokenPrice is in USD18,
// so the result is scaled by 1e18.
daConfig, err := c.ccipReader.GetMedianDataAvailabilityGasConfig(ctx)
if err != nil {
return nil, fmt.Errorf("unable to get data availability gas config: %w", err)
}

for _, msg := range messages {
executionCostUSD18 := c.computeExecutionCostUSD18(executionFee, msg)
dataAvailabilityCostUSD18 := computeDataAvailabilityCostUSD18(daFee, daConfig, msg)
executionCostUSD18 := c.computeExecutionCostUSD18(feeComponents.ExecutionFee, msg)
dataAvailabilityCostUSD18 := computeDataAvailabilityCostUSD18(feeComponents.DataAvailabilityFee, daConfig, msg)
totalCostUSD18 := new(big.Int).Add(executionCostUSD18, dataAvailabilityCostUSD18)
messageExecCosts[msg.Header.MessageID] = totalCostUSD18
}

return messageExecCosts, nil
}

func (c *CCIPMessageExecCostUSD18Calculator) getFeesUSD18(
ctx context.Context,
feeComponents types.ChainFeeComponents,
destChainSelector cciptypes.ChainSelector,
) (plugintypes.USD18, plugintypes.USD18, error) {
nativeTokenPrices := c.ccipReader.GetWrappedNativeTokenPriceUSD(
ctx,
[]cciptypes.ChainSelector{destChainSelector})
if nativeTokenPrices == nil {
return nil, nil, fmt.Errorf("unable to get native token prices")
}
nativeTokenPrice, ok := nativeTokenPrices[destChainSelector]
if !ok {
return nil, nil, fmt.Errorf("missing native token price for chain %s", destChainSelector)
}

if (feeComponents.ExecutionFee).Cmp(big.NewInt(0)) == 0 {
return big.NewInt(0), big.NewInt(0), nil
}
executionFee := new(big.Int).Div(nativeTokenPrice.Int, feeComponents.ExecutionFee)

if (feeComponents.DataAvailabilityFee).Cmp(big.NewInt(0)) == 0 {
return executionFee, big.NewInt(0), nil
}
dataAvailabilityFee := new(big.Int).Div(nativeTokenPrice.Int, feeComponents.DataAvailabilityFee)

return executionFee, dataAvailabilityFee, nil
}

// computeExecutionCostUSD18 computes the execution cost of a message in USD18s.
// The cost is:
// messageGas (gas) * executionFee (USD18/gas) = USD18
Expand All @@ -440,9 +388,7 @@ func computeDataAvailabilityCostUSD18(
}

messageGas := calculateMessageMaxDAGas(message, daConfig)
cost := big.NewInt(0).Mul(messageGas, dataAvailabilityFee)

return cost
return big.NewInt(0).Mul(messageGas, dataAvailabilityFee)
}

// calculateMessageMaxDAGas calculates the total DA gas needed for a CCIP message
Expand Down
74 changes: 31 additions & 43 deletions execute/exectypes/costly_messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,6 @@ func TestCCIPMessageFeeE18USDCalculator_MessageFeeE18USD(t *testing.T) {
}

func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
destChainSelector := ccipocr3.ChainSelector(1)
nativeTokenPrice := ccipocr3.BigInt{
Int: new(big.Int).Mul(big.NewInt(9), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))}

tests := []struct {
name string
messages []ccipocr3.Message
Expand All @@ -310,17 +306,17 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
name: "happy path, no DA cost",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
},
{
Header: ccipocr3.RampMessageHeader{MessageID: b2, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b2},
},
{
Header: ccipocr3.RampMessageHeader{MessageID: b3, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b3},
},
},
messageGases: []uint64{100, 200, 300},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(0),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
Expand All @@ -329,46 +325,46 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
DestDataAvailabilityMultiplierBps: 1,
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(45000000000), // 5_000_000_000 * 9 (price conversion)
b2: plugintypes.NewUSD18(90000000000), // 10_000_000_000 * 9
b3: plugintypes.NewUSD18(135000000000), // 15_000_000_000 * 9
b1: plugintypes.NewUSD18(10000),
b2: plugintypes.NewUSD18(20000),
b3: plugintypes.NewUSD18(30000),
},
wantErr: false,
},
{
name: "happy path, with DA cost",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
},
{
Header: ccipocr3.RampMessageHeader{MessageID: b2, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b2},
},
{
Header: ccipocr3.RampMessageHeader{MessageID: b3, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b3},
},
},
messageGases: []uint64{100, 200, 300},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
dataAvailabilityFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(400),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
DestDataAvailabilityOverheadGas: 1200,
DestGasPerDataAvailabilityByte: 10,
DestDataAvailabilityMultiplierBps: 200,
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(55170000000), // 4.5e10 (exec) + 1.017e10 (da)
b2: plugintypes.NewUSD18(100170000000), // 9e10 (exec) + 1.017e10 (da)
b3: plugintypes.NewUSD18(145170000000), // 135e10 (exec) + 1.017e10 (da)
b1: plugintypes.NewUSD18(55200), // 10_000 (exec) + 45_200 (da)
b2: plugintypes.NewUSD18(65200), // 20_000 (exec) + 45_200 (da)
b3: plugintypes.NewUSD18(75200), // 30_000 (exec) + 45_200 (da)
},
wantErr: false,
},
{
name: "message with token amounts affects DA gas calculation",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
TokenAmounts: []ccipocr3.RampTokenAmount{
{
SourcePoolAddress: []byte("source_pool"),
Expand All @@ -385,46 +381,46 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
},
},
messageGases: []uint64{100},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
dataAvailabilityFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(400),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
DestDataAvailabilityOverheadGas: 1000,
DestGasPerDataAvailabilityByte: 10,
DestDataAvailabilityMultiplierBps: 200,
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(60570000000), // 4.5e10 (exec) + 1.557e10 (da)
b1: plugintypes.NewUSD18(79200), // 10_000 (exec) + 69_200 (da)
},
wantErr: false,
},
{
name: "zero DA multiplier results in only overhead gas",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
Data: []byte("some_data"),
},
},
messageGases: []uint64{100},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
dataAvailabilityFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(400),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
DestDataAvailabilityOverheadGas: 1000,
DestGasPerDataAvailabilityByte: 10,
DestDataAvailabilityMultiplierBps: 0, // Zero multiplier
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(45000000000), // Only exec cost, DA cost is 0
b1: plugintypes.NewUSD18(10000), // Only exec cost, DA cost is 0
},
wantErr: false,
},
{
name: "large message with multiple tokens",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
TokenAmounts: []ccipocr3.RampTokenAmount{
{
SourcePoolAddress: make([]byte, 100), // Large token data
Expand All @@ -448,16 +444,16 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
},
},
messageGases: []uint64{100},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
dataAvailabilityFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(400),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
DestDataAvailabilityOverheadGas: 1000,
DestGasPerDataAvailabilityByte: 10,
DestDataAvailabilityMultiplierBps: 200,
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(92160000000), // 4.5e10 (exec) + 4.716e10 (da)
b1: plugintypes.NewUSD18(219600), // 10_000 (exec) + 218_600 (da)
},
wantErr: false,
},
Expand Down Expand Up @@ -490,20 +486,20 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
name: "minimal message - only constant parts",
messages: []ccipocr3.Message{
{
Header: ccipocr3.RampMessageHeader{MessageID: b1, DestChainSelector: destChainSelector},
Header: ccipocr3.RampMessageHeader{MessageID: b1},
},
},
messageGases: []uint64{100},
executionFee: new(big.Int).Mul(big.NewInt(20), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
dataAvailabilityFee: new(big.Int).Mul(big.NewInt(100), new(big.Int).Exp(big.NewInt(10), big.NewInt(9), nil)),
executionFee: big.NewInt(100),
dataAvailabilityFee: big.NewInt(400),
feeComponentsError: nil,
daGasConfig: ccipocr3.DataAvailabilityGasConfig{
DestDataAvailabilityOverheadGas: 1000,
DestGasPerDataAvailabilityByte: 10,
DestDataAvailabilityMultiplierBps: 200,
},
want: map[ccipocr3.Bytes32]plugintypes.USD18{
b1: plugintypes.NewUSD18(54810000000), // 4.5e10 (exec) + 0.981e10 (da)
b1: plugintypes.NewUSD18(53600), // 10_000 (exec) + 43_600 (da)
},
wantErr: false,
},
Expand All @@ -520,14 +516,6 @@ func TestCCIPMessageExecCostUSD18Calculator_MessageExecCostUSD18(t *testing.T) {
DataAvailabilityFee: tt.dataAvailabilityFee,
}
mockReader.EXPECT().GetDestChainFeeComponents(ctx).Return(feeComponents, tt.feeComponentsError)
mockReader.EXPECT().GetWrappedNativeTokenPriceUSD(
ctx,
[]ccipocr3.ChainSelector{destChainSelector},
).Return(
map[ccipocr3.ChainSelector]ccipocr3.BigInt{
destChainSelector: nativeTokenPrice,
},
).Maybe()
if !tt.wantErr {
mockReader.EXPECT().GetMedianDataAvailabilityGasConfig(ctx).Return(tt.daGasConfig, nil)
}
Expand Down
1 change: 0 additions & 1 deletion execute/plugin_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ func Test_ExcludingCostlyMessages(t *testing.T) {
tm := timeMachine{now: messageTimestamp}

intTest := SetupSimpleTest(t, srcSelector, dstSelector)

intTest.WithMessages(messages, 1000, messageTimestamp)
intTest.WithCustomFeeBoosting(1.0, tm.Now, map[cciptypes.Bytes32]plugintypes.USD18{
messages[0].Header.MessageID: plugintypes.NewUSD18(40000),
Expand Down
4 changes: 1 addition & 3 deletions execute/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
crand "crypto/rand"
"encoding/binary"
"math/big"
"net/http"
"net/http/httptest"
"strings"
Expand Down Expand Up @@ -387,8 +386,7 @@ type msgOption func(*cciptypes.Message)

func withFeeValueJuels(fee int64) msgOption {
return func(m *cciptypes.Message) {
juels := new(big.Int).Mul(big.NewInt(fee), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))
m.FeeValueJuels = cciptypes.NewBigInt(juels)
m.FeeValueJuels = cciptypes.NewBigIntFromInt64(fee)
}
}

Expand Down
4 changes: 0 additions & 4 deletions internal/plugintypes/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,3 @@ type USD18 = *big.Int
func NewUSD18(value int64) USD18 {
return big.NewInt(value)
}

func NewUSD18FromUSD(value int64) USD18 {
return new(big.Int).Mul(big.NewInt(value), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))
}

0 comments on commit 590a9fc

Please sign in to comment.