diff --git a/bindings/generated/latest/ccip/burnminttokenpool/burnminttokenpool.go b/bindings/generated/latest/ccip/burnminttokenpool/burnminttokenpool.go index 11b80f15a..40ef1acd4 100644 --- a/bindings/generated/latest/ccip/burnminttokenpool/burnminttokenpool.go +++ b/bindings/generated/latest/ccip/burnminttokenpool/burnminttokenpool.go @@ -29,7 +29,7 @@ var ( const ( PackageName = "ccip-burn-mint-token-pool" - PackageID = "9ccf8f8d55b079f34327e74076dfc14654ec2d87bbf89b12fb8d083f310e53c7" + PackageID = "fb14d9bf62df637430524e639c908a70456a67c40779fd86ecd72d566c49e18a" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/ccipruntime/ccipruntime.go b/bindings/generated/latest/ccip/ccipruntime/ccipruntime.go index d7cbbd528..9648dca82 100644 --- a/bindings/generated/latest/ccip/ccipruntime/ccipruntime.go +++ b/bindings/generated/latest/ccip/ccipruntime/ccipruntime.go @@ -32,7 +32,7 @@ var ( const ( PackageName = "ccip-runtime" - PackageID = "4e7fdb5823bb4bc7dcf956b500203b83e5b8c638c74c38e69208509d76260f98" + PackageID = "0c0908e6ee22e91a4ec9cb411c919134757bc857e719aedd2746674d89ba4ee3" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/client/client.go b/bindings/generated/latest/ccip/client/client.go index 0f1970871..90d429921 100644 --- a/bindings/generated/latest/ccip/client/client.go +++ b/bindings/generated/latest/ccip/client/client.go @@ -29,7 +29,7 @@ var ( const ( PackageName = "ccip-client" - PackageID = "e48e6bc72a97d717a0459c60840c792fce1c4e1927c3e1856266b1aee362d324" + PackageID = "e5e7d0df77722323b656350e5d5a3a31ce1ba9f876d6af615a513131d1aade5e" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/core/core.go b/bindings/generated/latest/ccip/core/core.go index 219e81c15..17be0ee1d 100644 --- a/bindings/generated/latest/ccip/core/core.go +++ b/bindings/generated/latest/ccip/core/core.go @@ -30,7 +30,7 @@ var ( const ( PackageName = "ccip-core" - PackageID = "b82df29f6afce1f274c15a391acc7577e22bda4dd1c3c665908180c1811b33bd" + PackageID = "a74a5d53a8f1acc873f10788c74494f6e5007a54067bd1dae303347c7041e3a5" SDKVersion = "3.4.11" ) @@ -5445,50 +5445,51 @@ func (t *RemovePriceUpdaters) UnmarshalHex(data string) error { // SendingMessage is a Template type type SendingMessage struct { - Deps SendingMessageDeps `json:"deps"` - CcipOwner types.PARTY `json:"ccipOwner"` - Sender types.PARTY `json:"sender"` - DestChainSelector types.NUMERIC `json:"destChainSelector"` - DestAddressBytesLength types.INT64 `json:"destAddressBytesLength"` - SequenceNumber types.NUMERIC `json:"sequenceNumber"` - DestDefaultCCVs []chainlinkapi.RawInstanceAddress `json:"destDefaultCCVs"` - RequiredCCVs []chainlinkapi.RawInstanceAddress `json:"requiredCCVs"` - RequiredExecutor *chainlinkapi.RawInstanceAddress `json:"requiredExecutor" hex:"optional"` - ExecutorAddress types.TEXT `json:"executorAddress"` - ExecutionMode *ExecutionMode `json:"executionMode" hex:"optional"` - SourceChainSelector types.NUMERIC `json:"sourceChainSelector"` - SenderAddress types.TEXT `json:"senderAddress"` - Receiver types.TEXT `json:"receiver"` - Payload types.TEXT `json:"payload"` - ExecutionGasLimit types.INT64 `json:"executionGasLimit"` - CcipReceiveGasLimit types.INT64 `json:"ccipReceiveGasLimit"` - CcvAndExecutorHash types.TEXT `json:"ccvAndExecutorHash"` - OnRampAddress types.TEXT `json:"onRampAddress"` - OffRampAddress types.TEXT `json:"offRampAddress" hex:"bytes"` - TokenReceiver types.TEXT `json:"tokenReceiver"` - TokenArgs types.TEXT `json:"tokenArgs"` - FeeToken splice_api_token_holding_v1.InstrumentId `json:"feeToken"` - NetworkFeeUSDCents types.NUMERIC `json:"networkFeeUSDCents"` - ExpectedTokenInstrumentId *splice_api_token_holding_v1.InstrumentId `json:"expectedTokenInstrumentId" hex:"optional"` - OutboundPoolCCVs *[]chainlinkapi.RawInstanceAddress `json:"outboundPoolCCVs" hex:"optional"` - ExecutorArgs types.TEXT `json:"executorArgs"` - ExecutorFee *ExecutorFee `json:"executorFee" hex:"optional"` - ExecutorDestGasLimit types.INT64 `json:"executorDestGasLimit"` - ExecutorDestBytesOverhead types.INT64 `json:"executorDestBytesOverhead"` - ExecutorFeeTokenAmount types.NUMERIC `json:"executorFeeTokenAmount"` - ObservingParties []types.PARTY `json:"observingParties"` - CcvFees []CCVFee `json:"ccvFees"` - TokenSendFee *TokenSendFee `json:"tokenSendFee" hex:"optional"` - CcvFeeTokenAmounts []types.NUMERIC `json:"ccvFeeTokenAmounts"` - TokenSendFeeTokenAmount types.NUMERIC `json:"tokenSendFeeTokenAmount"` - NetworkFeeTokenAmount types.NUMERIC `json:"networkFeeTokenAmount"` - TokenSendData *TokenSendData `json:"tokenSendData" hex:"optional"` - VerifierData []VerifierData `json:"verifierData"` - CcvOwners []types.PARTY `json:"ccvOwners"` - Message *ccipcodec.MessageV1 `json:"message" hex:"optional"` - EncodedMessage types.TEXT `json:"encodedMessage"` - MessageId types.TEXT `json:"messageId"` - State SendingMessageState `json:"state"` + Deps SendingMessageDeps `json:"deps"` + CcipOwner types.PARTY `json:"ccipOwner"` + Sender types.PARTY `json:"sender"` + DestChainSelector types.NUMERIC `json:"destChainSelector"` + DestAddressBytesLength types.INT64 `json:"destAddressBytesLength"` + SequenceNumber types.NUMERIC `json:"sequenceNumber"` + DestDefaultCCVs []chainlinkapi.RawInstanceAddress `json:"destDefaultCCVs"` + RequiredCCVs []chainlinkapi.RawInstanceAddress `json:"requiredCCVs"` + RequiredExecutor *chainlinkapi.RawInstanceAddress `json:"requiredExecutor" hex:"optional"` + ExecutorAddress types.TEXT `json:"executorAddress"` + ExecutionMode *ExecutionMode `json:"executionMode" hex:"optional"` + SourceChainSelector types.NUMERIC `json:"sourceChainSelector"` + SenderAddress types.TEXT `json:"senderAddress"` + Receiver types.TEXT `json:"receiver"` + Payload types.TEXT `json:"payload"` + ExecutionGasLimit types.INT64 `json:"executionGasLimit"` + CcipReceiveGasLimit types.INT64 `json:"ccipReceiveGasLimit"` + CcvAndExecutorHash types.TEXT `json:"ccvAndExecutorHash"` + OnRampAddress types.TEXT `json:"onRampAddress"` + OffRampAddress types.TEXT `json:"offRampAddress" hex:"bytes"` + TokenReceiver types.TEXT `json:"tokenReceiver"` + TokenArgs types.TEXT `json:"tokenArgs"` + FeeToken splice_api_token_holding_v1.InstrumentId `json:"feeToken"` + NetworkFeeUSDCents types.NUMERIC `json:"networkFeeUSDCents"` + ExpectedTokenInstrumentId *splice_api_token_holding_v1.InstrumentId `json:"expectedTokenInstrumentId" hex:"optional"` + TokenAmountBeforeTokenPoolFees types.NUMERIC `json:"tokenAmountBeforeTokenPoolFees"` + OutboundPoolCCVs *[]chainlinkapi.RawInstanceAddress `json:"outboundPoolCCVs" hex:"optional"` + ExecutorArgs types.TEXT `json:"executorArgs"` + ExecutorFee *ExecutorFee `json:"executorFee" hex:"optional"` + ExecutorDestGasLimit types.INT64 `json:"executorDestGasLimit"` + ExecutorDestBytesOverhead types.INT64 `json:"executorDestBytesOverhead"` + ExecutorFeeTokenAmount types.NUMERIC `json:"executorFeeTokenAmount"` + ObservingParties []types.PARTY `json:"observingParties"` + CcvFees []CCVFee `json:"ccvFees"` + TokenSendFee *TokenSendFee `json:"tokenSendFee" hex:"optional"` + CcvFeeTokenAmounts []types.NUMERIC `json:"ccvFeeTokenAmounts"` + TokenSendFeeTokenAmount types.NUMERIC `json:"tokenSendFeeTokenAmount"` + NetworkFeeTokenAmount types.NUMERIC `json:"networkFeeTokenAmount"` + TokenSendData *TokenSendData `json:"tokenSendData" hex:"optional"` + VerifierData []VerifierData `json:"verifierData"` + CcvOwners []types.PARTY `json:"ccvOwners"` + Message *ccipcodec.MessageV1 `json:"message" hex:"optional"` + EncodedMessage types.TEXT `json:"encodedMessage"` + MessageId types.TEXT `json:"messageId"` + State SendingMessageState `json:"state"` } // GetTemplateID returns the template ID for this template using the package name @@ -5623,6 +5624,10 @@ func (t SendingMessage) CreateCommand() *model.CreateCommand { } } + if t.TokenAmountBeforeTokenPoolFees != "" { + args["tokenAmountBeforeTokenPoolFees"] = t.TokenAmountBeforeTokenPoolFees + } + if t.OutboundPoolCCVs != nil { args["outboundPoolCCVs"] = map[string]any{ "_type": "optional", @@ -5887,6 +5892,10 @@ func (t SendingMessage) CreateCommandWithPackageID(packageID string) *model.Crea } } + if t.TokenAmountBeforeTokenPoolFees != "" { + args["tokenAmountBeforeTokenPoolFees"] = t.TokenAmountBeforeTokenPoolFees + } + if t.OutboundPoolCCVs != nil { args["outboundPoolCCVs"] = map[string]any{ "_type": "optional", diff --git a/bindings/generated/latest/ccip/events/events.go b/bindings/generated/latest/ccip/events/events.go index b5e085c03..fd013af1e 100644 --- a/bindings/generated/latest/ccip/events/events.go +++ b/bindings/generated/latest/ccip/events/events.go @@ -27,7 +27,7 @@ var ( const ( PackageName = "ccip-events" - PackageID = "ed745ab0d59b47a9988e7f420286c838a5d5ff5e16069c811b8702089fde01b7" + PackageID = "92570efbe4b4185cb0c651b85de70dfd9d9e8d5dc8e3aba2e923e4d7eb755924" SDKVersion = "3.4.11" ) @@ -195,12 +195,14 @@ func (t CCIPMessageSent) ArchiveWithPackageID(contractID string, packageID strin // CCIPMessageSentEvent is a Record type type CCIPMessageSentEvent struct { - DestChainSelector types.NUMERIC `json:"destChainSelector"` - SequenceNumber types.NUMERIC `json:"sequenceNumber"` - MessageId types.TEXT `json:"messageId"` - EncodedMessage types.TEXT `json:"encodedMessage"` - VerifierBlobs []types.TEXT `json:"verifierBlobs"` - Receipts []Receipt `json:"receipts"` + DestChainSelector types.NUMERIC `json:"destChainSelector"` + SequenceNumber types.NUMERIC `json:"sequenceNumber"` + MessageId types.TEXT `json:"messageId"` + FeeToken splice_api_token_holding_v1.InstrumentId `json:"feeToken"` + TokenAmountBeforeTokenPoolFees types.NUMERIC `json:"tokenAmountBeforeTokenPoolFees"` + EncodedMessage types.TEXT `json:"encodedMessage"` + VerifierBlobs []types.TEXT `json:"verifierBlobs"` + Receipts []Receipt `json:"receipts"` } // ToMap converts CCIPMessageSentEvent to a map for DAML arguments @@ -213,6 +215,10 @@ func (t CCIPMessageSentEvent) ToMap() map[string]any { m["messageId"] = string(t.MessageId) + m["feeToken"] = model.NestedToDAMLValue(t.FeeToken) + + m["tokenAmountBeforeTokenPoolFees"] = t.TokenAmountBeforeTokenPoolFees + m["encodedMessage"] = string(t.EncodedMessage) m["verifierBlobs"] = func() []any { diff --git a/bindings/generated/latest/ccip/factory/factory.go b/bindings/generated/latest/ccip/factory/factory.go index 9fe3b79d3..15aaa8303 100644 --- a/bindings/generated/latest/ccip/factory/factory.go +++ b/bindings/generated/latest/ccip/factory/factory.go @@ -36,7 +36,7 @@ var ( const ( PackageName = "ccip-factory" - PackageID = "702e83b25f9e8adc9f7d9257089177b36c7f84320f20b473c82f1bd7f072c522" + PackageID = "7b0160745bc279eba269b61becdcbf9f009ad0eec6d81a6189f111ed794b5814" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/lockreleasetokenpool/lockreleasetokenpool.go b/bindings/generated/latest/ccip/lockreleasetokenpool/lockreleasetokenpool.go index 640d501d3..f640d12cb 100644 --- a/bindings/generated/latest/ccip/lockreleasetokenpool/lockreleasetokenpool.go +++ b/bindings/generated/latest/ccip/lockreleasetokenpool/lockreleasetokenpool.go @@ -29,7 +29,7 @@ var ( const ( PackageName = "ccip-lock-release-token-pool" - PackageID = "4750763c7995b112ef5f44da7d38012b7926a16c301fcd88a570d2b784069085" + PackageID = "b7873783ebcc4e6fdaababc1fd9c4649bed7bf9e53f8eb19cd0fb9848057d3f7" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/receiver/receiver.go b/bindings/generated/latest/ccip/receiver/receiver.go index 79ef0cf77..ae1a73a61 100644 --- a/bindings/generated/latest/ccip/receiver/receiver.go +++ b/bindings/generated/latest/ccip/receiver/receiver.go @@ -27,7 +27,7 @@ var ( const ( PackageName = "ccip-receiver" - PackageID = "4846cc58edf50639f6394c6c185e2110de7b5c5b3f005998a2c346e7cf9e9a39" + PackageID = "54e58456501ffafb7d0d8e87afa4bdf0ba199585f5e7a28fee48d66dde9352d9" SDKVersion = "3.4.11" ) diff --git a/bindings/generated/latest/ccip/sender/sender.go b/bindings/generated/latest/ccip/sender/sender.go index f6cc2263d..aec43c321 100644 --- a/bindings/generated/latest/ccip/sender/sender.go +++ b/bindings/generated/latest/ccip/sender/sender.go @@ -26,7 +26,7 @@ var ( const ( PackageName = "ccip-sender" - PackageID = "9475bfd680dbcbc5c62cfa8b7f40ac3a5acacb62b54961855f662540e8e9e057" + PackageID = "f2db1b3d9ed0a030a286cec41852eef1cc627c8949682fe65e85ecabbb719e83" SDKVersion = "3.4.11" ) diff --git a/contracts/ccip/core/daml/CCIP/CoreV1/SendingMessage.daml b/contracts/ccip/core/daml/CCIP/CoreV1/SendingMessage.daml index 542c268f2..2ffa535df 100644 --- a/contracts/ccip/core/daml/CCIP/CoreV1/SendingMessage.daml +++ b/contracts/ccip/core/daml/CCIP/CoreV1/SendingMessage.daml @@ -230,6 +230,9 @@ template SendingMessage networkFeeUSDCents : Numeric 0 -- Expected token instrument for outbound TAR validation expectedTokenInstrumentId : Optional Splice.Api.Token.HoldingV1.InstrumentId + -- The original input amount of the message, before the pool deducts any fees. + -- Emitted in the CCIPMessageSent event + tokenAmountBeforeTokenPoolFees : Decimal -- Pool-required outbound CCVs, set via TAR authorization outboundPoolCCVs : Optional [Chainlink.InstanceAddress.RawInstanceAddress] -- Executor arguments, set during PrepareSend and validated by AddExecutorFee. @@ -630,6 +633,8 @@ template SendingMessage destChainSelector = destChainSelector sequenceNumber = sequenceNumber messageId = messageId + feeToken = feeToken + tokenAmountBeforeTokenPoolFees = tokenAmountBeforeTokenPoolFees encodedMessage = encodedMessage verifierBlobs = verifierBlobs receipts = receipts diff --git a/contracts/ccip/events/daml/CCIP/EventsV1/Events.daml b/contracts/ccip/events/daml/CCIP/EventsV1/Events.daml index 9738b198c..8aa983399 100644 --- a/contracts/ccip/events/daml/CCIP/EventsV1/Events.daml +++ b/contracts/ccip/events/daml/CCIP/EventsV1/Events.daml @@ -28,6 +28,8 @@ data CCIPMessageSentEvent = CCIPMessageSentEvent destChainSelector : Numeric 0 sequenceNumber : Numeric 0 messageId : BytesHex + feeToken : Splice.Api.Token.HoldingV1.InstrumentId + tokenAmountBeforeTokenPoolFees : Decimal encodedMessage : BytesHex verifierBlobs : [BytesHex] receipts : [CCIP.EventsV1.Receipts.Receipt] diff --git a/contracts/ccip/runtime/daml/CCIP/RuntimeV1/OnRamp.daml b/contracts/ccip/runtime/daml/CCIP/RuntimeV1/OnRamp.daml index 031d85387..2c072feb3 100644 --- a/contracts/ccip/runtime/daml/CCIP/RuntimeV1/OnRamp.daml +++ b/contracts/ccip/runtime/daml/CCIP/RuntimeV1/OnRamp.daml @@ -399,9 +399,9 @@ template OnRamp instrumentId = message.feeToken caller = ccipOwner - let (hasTokenTransfer, tokenInstrumentId) = case message.tokenTransfer of - None -> (False, None) - Some tt -> (True, Some tt.token) + let (hasTokenTransfer, tokenInstrumentId, tokenAmountBeforeTokenPoolFees) = case message.tokenTransfer of + None -> (False, None, 0.0) + Some tt -> (True, Some tt.token, tt.amount) let resolvedSenderRequiredCCVs = computeRequiredCCVsForSend destConfig @@ -476,6 +476,7 @@ template OnRamp feeToken = message.feeToken networkFeeUSDCents = networkFeeUSD expectedTokenInstrumentId = tokenInstrumentId + tokenAmountBeforeTokenPoolFees = tokenAmountBeforeTokenPoolFees outboundPoolCCVs = None executorAddress = resolvedExecutorAddress executionMode = executionMode diff --git a/contracts/ccip/test/daml/BurnMintTokenPoolTest.daml b/contracts/ccip/test/daml/BurnMintTokenPoolTest.daml index 8399fce9c..87610955b 100644 --- a/contracts/ccip/test/daml/BurnMintTokenPoolTest.daml +++ b/contracts/ccip/test/daml/BurnMintTokenPoolTest.daml @@ -233,6 +233,7 @@ mkSendingMessage ccipOwner sender rmnOwner rmnInstanceId tokenAdminRegistryInsta feeToken = instrumentId networkFeeUSDCents = 0.0 expectedTokenInstrumentId = Some instrumentId + tokenAmountBeforeTokenPoolFees = 10.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None diff --git a/contracts/ccip/test/daml/CCVMaxBounds.daml b/contracts/ccip/test/daml/CCVMaxBounds.daml index 3cbc0616a..ec1038596 100644 --- a/contracts/ccip/test/daml/CCVMaxBounds.daml +++ b/contracts/ccip/test/daml/CCVMaxBounds.daml @@ -356,6 +356,7 @@ mkSendingMessage ccipOwner sender destDefaultCCVs sequenceNumber = do feeToken = feeToken networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some tokenInstrumentId + tokenAmountBeforeTokenPoolFees = 10.0 outboundPoolCCVs = None executorArgs = "" executorFee = None diff --git a/contracts/ccip/test/daml/CommitteeVerifier/Test.daml b/contracts/ccip/test/daml/CommitteeVerifier/Test.daml index 35ca244d7..1fd05e46d 100644 --- a/contracts/ccip/test/daml/CommitteeVerifier/Test.daml +++ b/contracts/ccip/test/daml/CommitteeVerifier/Test.daml @@ -1051,6 +1051,7 @@ testForwardToVerifier_AllowlistChecksSender = script do feeToken = feeToken networkFeeUSDCents = 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None diff --git a/contracts/ccip/test/daml/FeeQuoter.daml b/contracts/ccip/test/daml/FeeQuoter.daml index 17bd265b4..faaee799c 100644 --- a/contracts/ccip/test/daml/FeeQuoter.daml +++ b/contracts/ccip/test/daml/FeeQuoter.daml @@ -577,6 +577,7 @@ testFinalizeFeeUsesEVMScaledPrices = script do feeToken = feeToken networkFeeUSDCents = cents 100.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -650,6 +651,7 @@ testAddCCVFeeRejectsWrongRawInstanceAddress = script do feeToken = feeToken networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -752,6 +754,7 @@ testFinalizeFee_PremiumAndExecutor = script do feeToken = feeToken networkFeeUSDCents = cents 100.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -872,6 +875,7 @@ testFinalizeFee_SmallFee = script do feeToken = feeToken networkFeeUSDCents = cents 1.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -979,6 +983,7 @@ testFinalizeFee_LinkCapAfterConversion = script do feeToken = feeToken networkFeeUSDCents = cents 150.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -1065,6 +1070,7 @@ testFinalizeFee_LinkCapDirect = script do feeToken = linkToken networkFeeUSDCents = cents 150.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -1152,6 +1158,7 @@ testFinalizeFee_LinkCapMixedFees = script do feeToken = linkToken networkFeeUSDCents = cents 100.0 expectedTokenInstrumentId = Some linkToken + tokenAmountBeforeTokenPoolFees = 10.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -1368,6 +1375,7 @@ testFinalizeFee_ReceiptSumsMatchQuoteInputs_MixedFees = script do feeToken = feeToken networkFeeUSDCents = cents 100.0 expectedTokenInstrumentId = Some feeToken + tokenAmountBeforeTokenPoolFees = 10.0 outboundPoolCCVs = Some [] executorArgs = "beef" executorFee = None @@ -1508,6 +1516,7 @@ testFinalizeFee_ReceiptSumsMatchQuoteInputs_CCVAndExecutor = script do feeToken = feeToken networkFeeUSDCents = cents 100.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "00" executorFee = None @@ -1646,6 +1655,7 @@ testFinalizeFee_PayloadBytesCountedOnce = script do feeToken = feeToken networkFeeUSDCents = 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None diff --git a/contracts/ccip/test/daml/LockReleaseTokenPoolTest.daml b/contracts/ccip/test/daml/LockReleaseTokenPoolTest.daml index 4c1428d83..efcedd28a 100644 --- a/contracts/ccip/test/daml/LockReleaseTokenPoolTest.daml +++ b/contracts/ccip/test/daml/LockReleaseTokenPoolTest.daml @@ -346,6 +346,7 @@ testLockOrBurn = script do feeToken = testInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 5.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -594,6 +595,7 @@ testLockOrBurnValidatesExistingPoolHoldingsAndPreservesThem = script do feeToken = testInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 5.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -784,6 +786,7 @@ testLockOrBurnDeductsFeeBps = script do feeToken = testInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 5.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -2244,6 +2247,7 @@ testExecutionGasLimitAggregation = script do feeToken = testInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -2500,6 +2504,7 @@ testExecutionGasLimitWithTokenSendFee = script do feeToken = testInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testTokenInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -2636,6 +2641,7 @@ testSetOutboundPoolCCVsResolvesDefaults = script do feeToken = feeInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some tokenInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -2729,6 +2735,7 @@ testAddTokenSendRejectsExtraDataBeyondQuotedOverhead = script do feeToken = testTokenInstrumentId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testTokenInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -3476,6 +3483,7 @@ testCalculateFeeFallsBackToFeeQuoter = script do feeToken = feeTokenId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -3630,6 +3638,7 @@ testCalculateFeePrefersPoolOverride = script do feeToken = feeTokenId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None @@ -3783,6 +3792,7 @@ testCalculateFeeFallsBackWhenPoolFeeDisabled = script do feeToken = feeTokenId networkFeeUSDCents = cents 0.0 expectedTokenInstrumentId = Some testInstrumentId + tokenAmountBeforeTokenPoolFees = 100.0 outboundPoolCCVs = Some [] executorArgs = "" executorFee = None diff --git a/contracts/ccip/test/daml/PerPartyRouter.daml b/contracts/ccip/test/daml/PerPartyRouter.daml index 666174811..423ebcd63 100644 --- a/contracts/ccip/test/daml/PerPartyRouter.daml +++ b/contracts/ccip/test/daml/PerPartyRouter.daml @@ -752,6 +752,8 @@ testCCIPSend = script do Some msgSent <- user `queryContractId` sendResult.ccipMessageSent msgSent.event.sequenceNumber === 1.0 msgSent.event.destChainSelector === destChainSelector + msgSent.event.feeToken === testFeeTokenId + msgSent.event.tokenAmountBeforeTokenPoolFees === 0.0 let decoded = fromSome (CCIP.CodecV1.MessageCodecV1.decodeMessageV1 msgSent.event.encodedMessage) decoded.executionGasLimit === 112345 diff --git a/contracts/ccip/test/daml/SendingMessageTest.daml b/contracts/ccip/test/daml/SendingMessageTest.daml index a3976d376..d2a59f2e6 100644 --- a/contracts/ccip/test/daml/SendingMessageTest.daml +++ b/contracts/ccip/test/daml/SendingMessageTest.daml @@ -59,6 +59,7 @@ testDistinctCcvOwnersWithSameInstanceId = script do feeToken = feeToken networkFeeUSDCents = 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None @@ -152,6 +153,7 @@ testSameOwnerDistinctInstanceIds = script do feeToken = feeToken networkFeeUSDCents = 0.0 expectedTokenInstrumentId = None + tokenAmountBeforeTokenPoolFees = 0.0 outboundPoolCCVs = None executorArgs = "" executorFee = None diff --git a/contracts/dars/current/ccip-burn-mint-token-pool-current.dar b/contracts/dars/current/ccip-burn-mint-token-pool-current.dar index 818394d97..e5812deef 100644 Binary files a/contracts/dars/current/ccip-burn-mint-token-pool-current.dar and b/contracts/dars/current/ccip-burn-mint-token-pool-current.dar differ diff --git a/contracts/dars/current/ccip-client-current.dar b/contracts/dars/current/ccip-client-current.dar index fbb2870a8..42e4d1521 100644 Binary files a/contracts/dars/current/ccip-client-current.dar and b/contracts/dars/current/ccip-client-current.dar differ diff --git a/contracts/dars/current/ccip-core-current.dar b/contracts/dars/current/ccip-core-current.dar index 05fe9eddf..520679412 100644 Binary files a/contracts/dars/current/ccip-core-current.dar and b/contracts/dars/current/ccip-core-current.dar differ diff --git a/contracts/dars/current/ccip-events-current.dar b/contracts/dars/current/ccip-events-current.dar index 649a3ac6e..8a71e313f 100644 Binary files a/contracts/dars/current/ccip-events-current.dar and b/contracts/dars/current/ccip-events-current.dar differ diff --git a/contracts/dars/current/ccip-factory-current.dar b/contracts/dars/current/ccip-factory-current.dar index 4aaab56e3..4c230af8d 100644 Binary files a/contracts/dars/current/ccip-factory-current.dar and b/contracts/dars/current/ccip-factory-current.dar differ diff --git a/contracts/dars/current/ccip-lock-release-token-pool-current.dar b/contracts/dars/current/ccip-lock-release-token-pool-current.dar index f1478c0b0..cfaaafef0 100644 Binary files a/contracts/dars/current/ccip-lock-release-token-pool-current.dar and b/contracts/dars/current/ccip-lock-release-token-pool-current.dar differ diff --git a/contracts/dars/current/ccip-receiver-current.dar b/contracts/dars/current/ccip-receiver-current.dar index e1fb657ab..32a31b267 100644 Binary files a/contracts/dars/current/ccip-receiver-current.dar and b/contracts/dars/current/ccip-receiver-current.dar differ diff --git a/contracts/dars/current/ccip-runtime-current.dar b/contracts/dars/current/ccip-runtime-current.dar index b24610ed1..f1ebf39ed 100644 Binary files a/contracts/dars/current/ccip-runtime-current.dar and b/contracts/dars/current/ccip-runtime-current.dar differ diff --git a/contracts/dars/current/ccip-sender-current.dar b/contracts/dars/current/ccip-sender-current.dar index 3ab361f8f..4661a217b 100644 Binary files a/contracts/dars/current/ccip-sender-current.dar and b/contracts/dars/current/ccip-sender-current.dar differ diff --git a/contracts/dars/current/ccip-test-current.dar b/contracts/dars/current/ccip-test-current.dar index 1075b07fa..b11da1b9d 100644 Binary files a/contracts/dars/current/ccip-test-current.dar and b/contracts/dars/current/ccip-test-current.dar differ diff --git a/integration-tests/ccip/ccip_send_test.go b/integration-tests/ccip/ccip_send_test.go index 03f31a739..76c138a81 100644 --- a/integration-tests/ccip/ccip_send_test.go +++ b/integration-tests/ccip/ccip_send_test.go @@ -35,11 +35,13 @@ import ( "github.com/smartcontractkit/go-daml/pkg/service/ledger" "github.com/smartcontractkit/go-daml/pkg/types" + "github.com/smartcontractkit/chainlink-canton/bindings" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipcodec" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipruntime" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/client" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/committeeverifier" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/core" + "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/events" executorBinding "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/executor" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/sender" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/chainlink/chainlinkapi" @@ -708,32 +710,28 @@ func TestCCIPSend(t *testing.T) { } } - // Extract messageId from CCIPMessageSent to verify success - var returnedMessageId string - var returnedEncodedMessage string + // Extract CIPMessageSent event to verify success + eventTemplateId := events.CCIPMessageSent{}.GetTemplateID() + var ccipMessageSent *events.CCIPMessageSent for _, event := range res.GetTransaction().GetEvents() { - if e, ok := event.GetEvent().(*apiv2.Event_Created); ok { - if e.Created.GetTemplateId().GetEntityName() == "CCIPMessageSent" { - fields := e.Created.GetCreateArguments().GetFields() - if len(fields) >= 5 { - // fields[4] is the "event" field (CCIPMessageSentEvent) - // (ccipOwner, ccvOwners, sender, observers, event) - eventField := fields[4].GetValue().GetRecord() - if eventField != nil && len(eventField.Fields) >= 4 { - // eventField.Fields[2] is messageId, eventField.Fields[3] is encodedMessage - returnedMessageId = eventField.Fields[2].GetValue().GetText() - if len(eventField.Fields) >= 4 { - returnedEncodedMessage = eventField.Fields[3].GetValue().GetText() - } - } + if createdEvent := event.GetCreated(); createdEvent != nil { + if templateId := createdEvent.GetTemplateId(); templateId != nil { + gotTemplateId := fmt.Sprintf("#%s:%s:%s", createdEvent.GetPackageName(), templateId.GetModuleName(), templateId.GetEntityName()) + if gotTemplateId == eventTemplateId { + // Found CCIPMessageSent event + ccipMessageSent, err = bindings.UnmarshalCreatedEvent[events.CCIPMessageSent](createdEvent) + require.NoError(t, err) + break } - - break } } } - require.NotEmpty(t, returnedMessageId, "CCIPMessageSent should be created") - require.NotEmpty(t, returnedEncodedMessage, "CCIPMessageSent should contain encoded message") + require.NotNil(t, ccipMessageSent, "CCIPMessageSent event not found") + require.NotEmpty(t, ccipMessageSent.Event.MessageId, "CCIPMessageSent should be created") + require.NotEmpty(t, ccipMessageSent.Event.EncodedMessage, "CCIPMessageSent should contain encoded message") + + // Verify that the event contains the feeToken InstrumentId + require.Equal(t, nativeInstrumentId, ccipMessageSent.Event.FeeToken, "CCIPMessageSent should contain feeToken InstrumentId") senderBalanceAfter, err := testhelpers.GetHoldingsBalance(t.Context(), senderParticipant, &nativeInstrumentId) require.NoError(t, err) @@ -750,9 +748,9 @@ func TestCCIPSend(t *testing.T) { require.Zero(t, ccipOwnerDelta.Cmp(quotedFeeAmount), "ccipOwner should receive the full quoted fee (executor is also owned by ccipOwner in this test)") t.Logf("Send completed") - t.Logf(" Message ID: %s", returnedMessageId) + t.Logf(" Message ID: %s", ccipMessageSent.Event.MessageId) t.Logf(" Original payload: %s", string(testPayload)) - t.Logf(" Encoded message: %s", returnedEncodedMessage) + t.Logf(" Encoded message: %s", ccipMessageSent.Event.EncodedMessage) t.Logf("✅ Success") } diff --git a/integration-tests/ccip/ccip_send_with_token_bnm_test.go b/integration-tests/ccip/ccip_send_with_token_bnm_test.go index 8e8bf11db..72fd5e3b4 100644 --- a/integration-tests/ccip/ccip_send_with_token_bnm_test.go +++ b/integration-tests/ccip/ccip_send_with_token_bnm_test.go @@ -36,12 +36,14 @@ import ( "github.com/smartcontractkit/go-daml/pkg/service/ledger" "github.com/smartcontractkit/go-daml/pkg/types" + "github.com/smartcontractkit/chainlink-canton/bindings" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/burnminttokenpool" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipcodec" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipruntime" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/client" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/committeeverifier" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/core" + "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/events" executorBinding "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/executor" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ratelimiter" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/sender" @@ -990,36 +992,37 @@ func TestBnMTokenPool_FullSendFlow(t *testing.T) { }) require.NoError(t, err) - // Extract messageId from CCIPMessageSent to verify success - var returnedMessageId string - var returnedEncodedMessage string + // Extract CIPMessageSent event to verify success + eventTemplateId := events.CCIPMessageSent{}.GetTemplateID() + var ccipMessageSent *events.CCIPMessageSent for _, event := range res.GetTransaction().GetEvents() { - if e, ok := event.GetEvent().(*apiv2.Event_Created); ok { - if e.Created.GetTemplateId().GetEntityName() == "CCIPMessageSent" { - fields := e.Created.GetCreateArguments().GetFields() - if len(fields) >= 5 { - eventField := fields[4].GetValue().GetRecord() - if eventField != nil { - for _, field := range eventField.Fields { - if field.GetLabel() == "messageId" { - returnedMessageId = field.GetValue().GetText() - } - if field.GetLabel() == "encodedMessage" { - returnedEncodedMessage = field.GetValue().GetText() - } - } - } + if createdEvent := event.GetCreated(); createdEvent != nil { + if templateId := createdEvent.GetTemplateId(); templateId != nil { + gotTemplateId := fmt.Sprintf("#%s:%s:%s", createdEvent.GetPackageName(), templateId.GetModuleName(), templateId.GetEntityName()) + if gotTemplateId == eventTemplateId { + // Found CCIPMessageSent event + ccipMessageSent, err = bindings.UnmarshalCreatedEvent[events.CCIPMessageSent](createdEvent) + require.NoError(t, err) + break } - - break } } } - require.NotEmpty(t, returnedMessageId, "CCIPMessageSent should be created") - require.NotEmpty(t, returnedEncodedMessage, "CCIPMessageSent should contain encoded message") + require.NotNil(t, ccipMessageSent, "CCIPMessageSent event not found") + require.NotEmpty(t, ccipMessageSent.Event.MessageId, "CCIPMessageSent should be created") + require.NotEmpty(t, ccipMessageSent.Event.EncodedMessage, "CCIPMessageSent should contain encoded message") + + // Verify that the event contains the feeToken InstrumentId + require.Equal(t, nativeInstrumentId, ccipMessageSent.Event.FeeToken, "CCIPMessageSent should contain feeToken InstrumentId") // Verify pool feeBps haircut: 10,000 smallest units with 5% feeBps => 9,500 bridged. - require.Equal(t, int64(9500), extractTokenTransferAmountFromEncodedMessageHex(t, returnedEncodedMessage), "encoded token amount should be net after 5% feeBps") + require.Equal(t, int64(9500), extractTokenTransferAmountFromEncodedMessageHex(t, ccipMessageSent.Event.EncodedMessage), "encoded token amount should be net after 5% feeBps") + // Verify that the event itself contains the original amount without fees + wantAmount, ok := new(big.Rat).SetString(tokenTransferAmountDecimal) + require.True(t, ok, "token transfer amount should parse as a decimal value") + gotAmount, ok := new(big.Rat).SetString(string(ccipMessageSent.Event.TokenAmountBeforeTokenPoolFees)) + require.True(t, ok, "token amount before token pool fees should parse as a decimal value") + require.Equal(t, 0, wantAmount.Cmp(gotAmount), "token amount before token pool fees should match original transfer amount") quotedFeeAmount, ok := new(big.Rat).SetString(feeStr) require.True(t, ok, "quoted fee should parse as a decimal value") @@ -1051,7 +1054,7 @@ func TestBnMTokenPool_FullSendFlow(t *testing.T) { }, 15*time.Second, 200*time.Millisecond, "sender LINK deduction should equal net token transfer amount after pool feeBps") t.Logf("Send completed") - t.Logf(" Message ID: %s", returnedMessageId) + t.Logf(" Message ID: %s", ccipMessageSent.Event.MessageId) t.Logf(" Original payload: %s", string(testPayload)) t.Logf("✅ Success") diff --git a/integration-tests/ccip/ccip_send_with_token_lnr_test.go b/integration-tests/ccip/ccip_send_with_token_lnr_test.go index 2820173b8..d1a1fd95c 100644 --- a/integration-tests/ccip/ccip_send_with_token_lnr_test.go +++ b/integration-tests/ccip/ccip_send_with_token_lnr_test.go @@ -35,11 +35,13 @@ import ( "github.com/smartcontractkit/go-daml/pkg/service/ledger" "github.com/smartcontractkit/go-daml/pkg/types" + "github.com/smartcontractkit/chainlink-canton/bindings" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipcodec" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ccipruntime" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/client" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/committeeverifier" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/core" + "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/events" executorBinding "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/executor" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/lockreleasetokenpool" "github.com/smartcontractkit/chainlink-canton/bindings/generated/latest/ccip/ratelimiter" @@ -938,36 +940,37 @@ func TestLnRTokenPool_FullSendFlow(t *testing.T) { }) require.NoError(t, err) - // Extract messageId from CCIPMessageSent to verify success - var returnedMessageId string - var returnedEncodedMessage string + // Extract CIPMessageSent event to verify success + eventTemplateId := events.CCIPMessageSent{}.GetTemplateID() + var ccipMessageSent *events.CCIPMessageSent for _, event := range res.GetTransaction().GetEvents() { - if e, ok := event.GetEvent().(*apiv2.Event_Created); ok { - if e.Created.GetTemplateId().GetEntityName() == "CCIPMessageSent" { - fields := e.Created.GetCreateArguments().GetFields() - if len(fields) >= 5 { - eventField := fields[4].GetValue().GetRecord() - if eventField != nil { - for _, field := range eventField.Fields { - if field.GetLabel() == "messageId" { - returnedMessageId = field.GetValue().GetText() - } - if field.GetLabel() == "encodedMessage" { - returnedEncodedMessage = field.GetValue().GetText() - } - } - } + if createdEvent := event.GetCreated(); createdEvent != nil { + if templateId := createdEvent.GetTemplateId(); templateId != nil { + gotTemplateId := fmt.Sprintf("#%s:%s:%s", createdEvent.GetPackageName(), templateId.GetModuleName(), templateId.GetEntityName()) + if gotTemplateId == eventTemplateId { + // Found CCIPMessageSent event + ccipMessageSent, err = bindings.UnmarshalCreatedEvent[events.CCIPMessageSent](createdEvent) + require.NoError(t, err) + break } - - break } } } - require.NotEmpty(t, returnedMessageId, "CCIPMessageSent should be created") - require.NotEmpty(t, returnedEncodedMessage, "CCIPMessageSent should contain encoded message") + require.NotNil(t, ccipMessageSent, "CCIPMessageSent event not found") + require.NotEmpty(t, ccipMessageSent.Event.MessageId, "CCIPMessageSent should be created") + require.NotEmpty(t, ccipMessageSent.Event.EncodedMessage, "CCIPMessageSent should contain encoded message") + + // Verify that the event contains the feeToken InstrumentId + require.Equal(t, nativeInstrumentId, ccipMessageSent.Event.FeeToken, "CCIPMessageSent should contain feeToken InstrumentId") // Verify pool feeBps haircut: 10,000 smallest units with 5% feeBps => 9,500 bridged. - require.Equal(t, int64(9500), extractTokenTransferAmountFromEncodedMessageHex(t, returnedEncodedMessage), "encoded token amount should be net after 5% feeBps") + require.Equal(t, int64(9500), extractTokenTransferAmountFromEncodedMessageHex(t, ccipMessageSent.Event.EncodedMessage), "encoded token amount should be net after 5% feeBps") + // Verify that the event itself contains the original amount without fees + wantAmount, ok := new(big.Rat).SetString(tokenTransferAmountDecimal) + require.True(t, ok, "token transfer amount should parse as a decimal value") + gotAmount, ok := new(big.Rat).SetString(string(ccipMessageSent.Event.TokenAmountBeforeTokenPoolFees)) + require.True(t, ok, "token amount before token pool fees should parse as a decimal value") + require.Equal(t, 0, wantAmount.Cmp(gotAmount), "token amount before token pool fees should match original transfer amount") // LnR LockOrBurn transfers gross to poolOwner; when poolOwner==sender, party Amulet total only drops by CCIP fee. require.Eventually(t, func() bool { @@ -981,7 +984,7 @@ func TestLnRTokenPool_FullSendFlow(t *testing.T) { }, 15*time.Second, 200*time.Millisecond, "sender Amulet deduction should equal GetFee feeTokenAmount only") t.Logf("Send completed") - t.Logf(" Message ID: %s", returnedMessageId) + t.Logf(" Message ID: %s", ccipMessageSent.Event.MessageId) t.Logf(" Original payload: %s", string(testPayload)) t.Logf("✅ Success") @@ -991,10 +994,10 @@ func TestLnRTokenPool_FullSendFlow(t *testing.T) { // tokenTransfer.amount (uint256 big-endian) from the token-transfer payload. // It skips the fixed CCIP message prefix, short variable fields, and destination blob, // then reads the amount from bytes [1:33] of tokenTransfer (byte 0 is version/tag). -func extractTokenTransferAmountFromEncodedMessageHex(t *testing.T, encodedMessageHex string) int64 { +func extractTokenTransferAmountFromEncodedMessageHex(t *testing.T, encodedMessageHex types.TEXT) int64 { t.Helper() - b, err := hex.DecodeString(encodedMessageHex) + b, err := hex.DecodeString(string(encodedMessageHex)) require.NoError(t, err, "decode encodedMessage") i := 1 + 8 + 8 + 8 + 4 + 4 + 4 + 32