-
Notifications
You must be signed in to change notification settings - Fork 3
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
Add DA cost estimation to CCIPMessageExecCostUSD18Calculator #275
Changes from all commits
e7913cf
3440f84
ab38be9
f586cc9
c9312f8
4eba17b
f136625
515f11e
5a53390
1663322
db73459
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,13 @@ import ( | |
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" | ||
) | ||
|
||
const ( | ||
EVMWordBytes = 32 | ||
MessageFixedBytesPerToken = 32 * ((2 * 3) + 3) | ||
ConstantMessagePartBytes = 32 * 14 // A message consists of 14 abi encoded fields 32B each (after encoding) | ||
daMultiplierBase = 10_000 // DA multiplier is in multiples of 0.0001, i.e. 1/daMultiplierBase | ||
) | ||
|
||
// CostlyMessageObserver observes messages that are too costly to execute. | ||
type CostlyMessageObserver interface { | ||
// Observe takes a set of messages and returns a slice of message IDs that are too costly to execute. | ||
|
@@ -340,11 +347,17 @@ func (c *CCIPMessageExecCostUSD18Calculator) MessageExecCostUSD18( | |
if feeComponents.ExecutionFee == nil { | ||
return nil, fmt.Errorf("missing execution fee") | ||
} | ||
if feeComponents.DataAvailabilityFee == nil { | ||
return nil, fmt.Errorf("missing data availability fee") | ||
} | ||
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(feeComponents.ExecutionFee, msg) | ||
// TODO: implement data availability cost | ||
dataAvailabilityCostUSD18 := new(big.Int) | ||
dataAvailabilityCostUSD18 := computeDataAvailabilityCostUSD18(feeComponents.DataAvailabilityFee, daConfig, msg) | ||
totalCostUSD18 := new(big.Int).Add(executionCostUSD18, dataAvailabilityCostUSD18) | ||
messageExecCosts[msg.Header.MessageID] = totalCostUSD18 | ||
} | ||
|
@@ -364,4 +377,49 @@ func (c *CCIPMessageExecCostUSD18Calculator) computeExecutionCostUSD18( | |
return cost | ||
} | ||
|
||
// computeDataAvailabilityCostUSD18 computes the data availability cost of a message in USD18s. | ||
func computeDataAvailabilityCostUSD18( | ||
dataAvailabilityFee *big.Int, | ||
daConfig cciptypes.DataAvailabilityGasConfig, | ||
message cciptypes.Message, | ||
) plugintypes.USD18 { | ||
if dataAvailabilityFee == nil || dataAvailabilityFee.Cmp(big.NewInt(0)) == 0 { | ||
return big.NewInt(0) | ||
} | ||
|
||
messageGas := calculateMessageMaxDAGas(message, daConfig) | ||
return big.NewInt(0).Mul(messageGas, dataAvailabilityFee) | ||
} | ||
|
||
// calculateMessageMaxDAGas calculates the total DA gas needed for a CCIP message | ||
func calculateMessageMaxDAGas( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DA is quite specific to EVM, I'm not expert of v2 code base, wondering if you want to put it under an EVM folder somewhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You right. We will work on making this logic chain abstracted in a second step There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The priority is to unblock the itests right now, so our plan is to merge this, then move this logic to chainlink with the other EVM specific logic |
||
msg cciptypes.Message, | ||
daConfig cciptypes.DataAvailabilityGasConfig, | ||
) *big.Int { | ||
// Calculate token data length | ||
var totalTokenDataLen int | ||
for _, tokenAmount := range msg.TokenAmounts { | ||
0xnogo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
totalTokenDataLen += MessageFixedBytesPerToken + | ||
len(tokenAmount.ExtraData) + | ||
len(tokenAmount.DestExecData) | ||
} | ||
|
||
// Calculate total message data length | ||
dataLen := ConstantMessagePartBytes + | ||
len(msg.Data) + | ||
len(msg.Sender) + | ||
totalTokenDataLen | ||
|
||
// Calculate base gas cost | ||
dataGas := big.NewInt(int64(dataLen)) | ||
dataGas = new(big.Int).Mul(dataGas, big.NewInt(int64(daConfig.DestGasPerDataAvailabilityByte))) | ||
dataGas = new(big.Int).Add(dataGas, big.NewInt(int64(daConfig.DestDataAvailabilityOverheadGas))) | ||
|
||
// Then apply the multiplier as: (dataGas * daMultiplier) / multiplierBase | ||
dataGas = new(big.Int).Mul(dataGas, big.NewInt(int64(daConfig.DestDataAvailabilityMultiplierBps))) | ||
dataGas = new(big.Int).Div(dataGas, big.NewInt(daMultiplierBase)) | ||
|
||
return dataGas | ||
} | ||
|
||
var _ MessageExecCostUSD18Calculator = &CCIPMessageExecCostUSD18Calculator{} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this actually returning fee in USD or fee in the native currency?
there is a pre-existing comment that says
executionFee (USD18/gas)
so I presume dataAvailabilityFee is denoted in USD/gas as opposed to native/gas, but after reading the code, it seemsfeeComponents
is read straight from the ChainWriter, does chain writer return native/gas (which I thought should be the case and will make this impl incorrect). or actually usd/gas, please double checkThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value is read from https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/ccip/FeeQuoter.sol#L303
which is denominated in USD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like USD/gas: https://github.com/smartcontractkit/chainlink/blob/a1e4f8e960d4b5bf05e353dec3254d13c9a3b4c8/contracts/src/v0.8/ccip/FeeQuoter.sol#L303
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still confused, isn't the value fetched from ChainWriter, maybe I missed it, where is it read from FeeQuoter?