-
Notifications
You must be signed in to change notification settings - Fork 5
Address gobinding inconsistency #566
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
Changes from 3 commits
946f753
a5d1bb7
a0c563c
06bb728
2e08c67
ccfd578
9288fb2
acb13df
01f5aaf
692c1da
0915be7
46e4e6e
76668ff
3949377
ef49fb1
0eb22b3
cddbd91
8f22724
8bd05ea
cb75692
35403ee
51d4d96
ebd64c8
5e5b92a
2724afa
9b0739c
6099e1f
018738d
c2ef0ca
6c78684
c2e5de8
00c9629
59aa374
e6eb97f
2b3f681
eb90f3d
68ca520
deb3a42
f338ac7
03a7970
bdf8980
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 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,16 +7,14 @@ import ( | |||||||||||
| "github.com/xssnick/tonutils-go/tlb" | ||||||||||||
| "github.com/xssnick/tonutils-go/tvm/cell" | ||||||||||||
|
|
||||||||||||
| "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/feequoter" | ||||||||||||
| "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" | ||||||||||||
| "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/router" | ||||||||||||
| "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| // CCIPSend Executor opcodes | ||||||||||||
| const ( | ||||||||||||
| OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') | ||||||||||||
| OpcodeFeeQuoterMessageValidated = 0x1fa60374 // crc32('FeeQuoter_MessageValidated') | ||||||||||||
| OpcodeFeeQuoterMessageValidationFailed = 0xbcf0ab0f // crc32('FeeQuoter_MessageValidationFailed') | ||||||||||||
| OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| //go:generate go run golang.org/x/tools/cmd/stringer@v0.38.0 -type=ExitCode | ||||||||||||
|
|
@@ -48,28 +46,13 @@ type Execute struct { | |||||||||||
| Config *cell.Cell `tlb:"^"` | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // FeeQuoter_MessageValidated message structure | ||||||||||||
| type MessageValidated struct { | ||||||||||||
| _ tlb.Magic `tlb:"#cbc4af76" json:"-"` //nolint:revive // Ignore opcode tag | ||||||||||||
| Fee *tlb.Coins `tlb:"."` | ||||||||||||
| Msg *router.CCIPSend `tlb:"^"` | ||||||||||||
| Metadata *cell.Cell `tlb:"^"` | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // FeeQuoter_MessageValidationFailed message structure | ||||||||||||
| type MessageValidationFailed struct { | ||||||||||||
| _ tlb.Magic `tlb:"#0f756150" json:"-"` //nolint:revive // Ignore opcode tag | ||||||||||||
| Error *big.Int `tlb:"## 256"` | ||||||||||||
| Msg *router.CCIPSend `tlb:"^"` | ||||||||||||
| Context *cell.Cell `tlb:"^"` | ||||||||||||
| } | ||||||||||||
| // MessageValidated and MessageValidationFailed are reused from the feequoter package | ||||||||||||
| // to ensure schema consistency with the on-chain FeeQuoter contract responses. | ||||||||||||
|
|
||||||||||||
| var TLBs = tvm.MustNewTLBMap([]any{ | ||||||||||||
| Execute{}, | ||||||||||||
| MessageValidated{}, | ||||||||||||
| MessageValidationFailed{}, | ||||||||||||
| // Note: We don't handle JettonTransferNotification or FeeQuoter_MessageValidated here | ||||||||||||
| // because they are already handled by their respective decoders (jetton wallet and fee quoter) | ||||||||||||
| feequoter.MessageValidated{}, | ||||||||||||
huangzhen1997 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||
| feequoter.MessageValidationFailed{}, | ||||||||||||
| }).MustWithStorageType(InitialData{}) | ||||||||||||
|
|
||||||||||||
| // Metadata structure | ||||||||||||
|
|
@@ -104,6 +87,6 @@ type StateOnGoingFeeValidation struct { | |||||||||||
|
|
||||||||||||
| // TokenAmount structure (reused from router package concept) | ||||||||||||
|
||||||||||||
| // TokenAmount structure (reused from router package concept) | |
| // TokenAmount represents an amount of a given token for the CCIP Send Executor. | |
| // It intentionally mirrors the schema and naming of router.TokenAmount instead of | |
| // reusing that type directly, to keep this bindings package self-contained and to | |
| // match the on-chain / TLB schema for executor messages. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,19 +84,23 @@ const ( | |
| ) | ||
|
|
||
| type Storage struct { | ||
| ID uint32 `tlb:"## 32"` | ||
| Ownable ownable2step.Storage `tlb:"."` | ||
| AllowedPriceUpdaters *cell.Dictionary `tlb:"dict 267"` | ||
| MaxFeeJuelsPerMsg *big.Int `tlb:"## 96"` | ||
| LinkToken *address.Address `tlb:"addr"` | ||
| TokenPriceStalenessThreshold uint64 `tlb:"## 64"` | ||
| UsdPerToken *cell.Dictionary `tlb:"dict 267"` | ||
| PremiumMultiplierWeiPerEth *cell.Dictionary `tlb:"dict 267"` | ||
| DestChainConfigs *cell.Dictionary `tlb:"dict 64"` | ||
| } | ||
|
|
||
| ID uint32 `tlb:"## 32"` | ||
| Ownable ownable2step.Storage `tlb:"."` | ||
| AllowedPriceUpdaters *cell.Dictionary `tlb:"dict 267"` | ||
krebernisak marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| MaxFeeJuelsPerMsg *big.Int `tlb:"## 96"` | ||
| LinkToken *address.Address `tlb:"addr"` | ||
| // TODO: Consider changing to uint32 for EVM compatibility. Currently uint64 on-chain. | ||
|
||
| TokenPriceStalenessThreshold uint64 `tlb:"## 64"` | ||
huangzhen1997 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| UsdPerToken *cell.Dictionary `tlb:"dict 267"` | ||
| PremiumMultiplierWeiPerEth *cell.Dictionary `tlb:"dict 267"` | ||
| DestChainConfigs *cell.Dictionary `tlb:"dict 64"` | ||
| } | ||
|
|
||
| // DestChainConfigs represents the full on-chain DestChainConfig struct from the FeeQuoter contract. | ||
| // See contracts/contracts/ccip/fee_quoter/types.tolk for the on-chain definition. | ||
| // Note the naming: this Go type uses plural "Configs" to distinguish from DestChainConfig above. | ||
| type DestChainConfigs struct { | ||
| Config DestChainConfig `tlb:"."` // inline struct | ||
| Config DestChainConfig `tlb:"."` // inline struct (FeeQuoterDestChainConfig on-chain) | ||
| USDPerUnitGasRef *cell.Cell `tlb:"^"` // ^Cell<GasPrice> | ||
| TokenTransferFeeConfigs *cell.Dictionary `tlb:"dict 267"` // map<address, TokenTransferFeeConfig> | ||
| } | ||
|
|
@@ -122,6 +126,12 @@ func (u *USDPerUnitGas) GetterMethodName() string { | |
| return destinationChainGasPriceGetter | ||
| } | ||
|
|
||
| // DestChainConfig represents the FeeQuoterDestChainConfig fields from the on-chain FeeQuoter contract. | ||
| // | ||
| // NOTE: This Go type is named "DestChainConfig" but corresponds to the on-chain "FeeQuoterDestChainConfig" | ||
| // struct (see contracts/contracts/ccip/fee_quoter/types.tolk). The on-chain "DestChainConfig" is a larger | ||
| // struct that wraps FeeQuoterDestChainConfig along with usdPerUnitGas and tokenTransferFeeConfigs fields. | ||
|
Collaborator
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. Thanks for the comment - imo this is super confusing and the naming is not best we can do. |
||
| // The full on-chain struct is represented by DestChainConfigs (plural) in this package. | ||
| type DestChainConfig struct { | ||
| IsEnabled bool `tlb:"bool"` | ||
| MaxNumberOfTokensPerMsg uint16 `tlb:"## 16"` | ||
|
|
@@ -205,30 +215,36 @@ type FeeToken struct { | |
| // Methods | ||
|
|
||
| // Generic wrapper for fee quoter messages with context | ||
| // NOTE: Context is T=RemainingBitsAndRefs on-chain, meaning the remaining bits/refs | ||
| // are written inline with no presence bit and no ref cell. | ||
| type GetValidatedFee struct { | ||
| _ tlb.Magic `tlb:"#7496FF56" json:"-"` //nolint:revive // Ignore opcode tag | ||
| Msg *cell.Cell `tlb:"^"` // Cell containing the CCIPSend message | ||
| Context *cell.Cell `tlb:"maybe ^"` // Cell containing context | ||
| Context *cell.Cell `tlb:"."` // Remaining bits/refs written inline | ||
| } | ||
|
|
||
| // --- Response from GetValidatedFee --- | ||
| // NOTE: Context is T=RemainingBitsAndRefs on-chain, meaning the remaining bits/refs | ||
| // are written inline with no presence bit and no ref cell. | ||
| type MessageValidated struct { | ||
| _ tlb.Magic `tlb:"#1fa60374" json:"-"` //nolint:revive // Ignore opcode tag | ||
| Fee Fee `tlb:"."` | ||
| Msg *cell.Cell `tlb:"^"` // Original message | ||
| Context *cell.Cell `tlb:"maybe ^"` // Original context | ||
| Msg *cell.Cell `tlb:"^"` // Original message | ||
| Context *cell.Cell `tlb:"."` // Remaining bits/refs written inline | ||
| } | ||
|
|
||
| type Fee struct { | ||
| FeeTokenAmount *tlb.Coins `tlb:"."` // fee value in fee token | ||
| FeeValueJuels *big.Int `tlb:"## 96"` // fee value in juels | ||
| } | ||
|
|
||
| // NOTE: Context is T=RemainingBitsAndRefs on-chain, meaning the remaining bits/refs | ||
| // are written inline with no presence bit and no ref cell. | ||
| type MessageValidationFailed struct { | ||
| _ tlb.Magic `tlb:"#bcf0ab0f" json:"-"` //nolint:revive // Ignore opcode tag | ||
| ErrorCode *big.Int `tlb:"## 256"` | ||
| Msg *cell.Cell `tlb:"^"` // Original message, | ||
| Context *cell.Cell `tlb:"maybe ^"` // Original context | ||
| Msg *cell.Cell `tlb:"^"` // Original message | ||
| Context *cell.Cell `tlb:"."` // Remaining bits/refs written inline | ||
| } | ||
|
|
||
| type AddPriceUpdater struct { | ||
|
|
@@ -254,13 +270,17 @@ type UpdateFeeTokens struct { | |
| Remove common.SnakedCell[common.AddressWrap] `tlb:"^"` | ||
| } | ||
|
|
||
| // UpdateTokenTransferFeeConfig is a value type stored in a dictionary, NOT a message. | ||
| // It represents per-destination-chain token transfer fee config updates. | ||
| type UpdateTokenTransferFeeConfig struct { | ||
| _ tlb.Magic `tlb:"#B2826316" json:"-"` //nolint:revive // Ignore opcode tag | ||
| Add map[*address.Address]TokenTransferFeeConfig | ||
| Remove []*address.Address `tlb:"addr"` | ||
| Add *cell.Dictionary `tlb:"dict 267"` // map<address, TokenTransferFeeConfig> | ||
krebernisak marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Remove common.SnakedCell[common.AddressWrap] `tlb:"^"` // SnakedCell<address> | ||
| } | ||
|
|
||
| // UpdateTokenTransferFeeConfigs is the message type for updating token transfer fee configs. | ||
| type UpdateTokenTransferFeeConfigs struct { | ||
| _ tlb.Magic `tlb:"#B2826316" json:"-"` //nolint:revive // Ignore opcode tag | ||
| _ tlb.Magic `tlb:"#B2826316" json:"-"` //nolint:revive // Ignore opcode tag | ||
| Updates *cell.Dictionary `tlb:"dict 64"` // map<uint64, UpdateTokenTransferFeeConfig> | ||
| } | ||
|
|
||
| type UpdateDestChainConfig struct { | ||
|
|
@@ -288,9 +308,10 @@ var TLBs = tvm.MustNewTLBMap([]any{ | |
| // binding types that supports FetchResult interface with rpc client | ||
|
|
||
| type StaticConfig struct { | ||
| MaxFeeJuelsPerMsg *big.Int | ||
| LinkToken *address.Address | ||
| StalenessThreshold uint32 | ||
| MaxFeeJuelsPerMsg *big.Int | ||
| LinkToken *address.Address | ||
| // TODO: Consider changing to uint32 for EVM compatibility once on-chain is updated. | ||
| StalenessThreshold uint64 | ||
| } | ||
|
|
||
| // Deprecated: Use GetStaticConfig getter instead. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,85 @@ | ||
| package feequoter | ||
|
|
||
| import "math/big" | ||
| import ( | ||
| "errors" | ||
| "math/big" | ||
| ) | ||
|
|
||
| var ( | ||
| // ErrNilGasPrice is returned when a nil gas price is passed to PackGasPrice. | ||
| ErrNilGasPrice = errors.New("gas price cannot be nil") | ||
| // ErrNegativeGasPrice is returned when a negative gas price is passed to PackGasPrice. | ||
| ErrNegativeGasPrice = errors.New("gas price cannot be negative") | ||
| // ErrGasPriceExceeds112Bits is returned when a gas price exceeds 112 bits. | ||
| ErrGasPriceExceeds112Bits = errors.New("gas price exceeds 112 bits") | ||
| // ErrPackedPriceExceeds224Bits is returned when a packed price exceeds 224 bits. | ||
| ErrPackedPriceExceeds224Bits = errors.New("packed price exceeds 224 bits") | ||
| // ErrNilPackedPrice is returned when a nil packed price is passed to UnpackGasPrice. | ||
| ErrNilPackedPrice = errors.New("packed price cannot be nil") | ||
| // ErrNegativePackedPrice is returned when a negative packed price is passed to UnpackGasPrice. | ||
| ErrNegativePackedPrice = errors.New("packed price cannot be negative") | ||
| ) | ||
|
|
||
| // maxUint112 is 2^112 - 1, can also be used as a mask for lower 112 bits sets to 1 | ||
| var maxUint112 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 112), big.NewInt(1)) | ||
huangzhen1997 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // maxUint224 is 2^224 - 1 | ||
| var maxUint224 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 224), big.NewInt(1)) | ||
|
|
||
| // PackGasPrice packs execution and data availability gas prices into a single 224-bit value. | ||
| // The packed format is: (dataAvailabilityGasPrice << 112) | executionGasPrice | ||
| // | ||
| // This matches the CCIP commit plugin's FeeComponentsToPackedFee function: | ||
| // https://github.com/smartcontractkit/chainlink-ccip/blob/main/commit/chainfee/outcome.go | ||
| func PackGasPrice(executionGasPrice, dataAvailabilityGasPrice *big.Int) *big.Int { | ||
| // | ||
| // Returns an error if: | ||
| // - Either input is nil | ||
| // - Either input is negative | ||
| // - Either input exceeds 112 bits | ||
| func PackGasPrice(executionGasPrice, dataAvailabilityGasPrice *big.Int) (*big.Int, error) { | ||
| if executionGasPrice == nil || dataAvailabilityGasPrice == nil { | ||
| return nil, ErrNilGasPrice | ||
| } | ||
| if executionGasPrice.Sign() < 0 || dataAvailabilityGasPrice.Sign() < 0 { | ||
| return nil, ErrNegativeGasPrice | ||
| } | ||
| if executionGasPrice.Cmp(maxUint112) > 0 { | ||
| return nil, ErrGasPriceExceeds112Bits | ||
| } | ||
| if dataAvailabilityGasPrice.Cmp(maxUint112) > 0 { | ||
| return nil, ErrGasPriceExceeds112Bits | ||
| } | ||
|
|
||
| daShifted := new(big.Int).Lsh(dataAvailabilityGasPrice, 112) | ||
| return new(big.Int).Or(daShifted, executionGasPrice) | ||
| return new(big.Int).Or(daShifted, executionGasPrice), nil | ||
| } | ||
|
|
||
| // UnpackGasPrice unpacks a 224-bit packed gas price value into separate execution | ||
| // and data availability gas prices. | ||
| // | ||
| // The packed format is: (dataAvailabilityGasPrice << 112) | executionGasPrice | ||
| // | ||
| // Returns an error if: | ||
| // - The input is nil | ||
| // - The input is negative | ||
| // - The input exceeds 224 bits | ||
| // | ||
| // Returns: | ||
| // - executionGasPrice: the lower 112 bits | ||
| // - dataAvailabilityGasPrice: the upper 112 bits | ||
| func UnpackGasPrice(packedPrice *big.Int) (executionGasPrice, dataAvailabilityGasPrice *big.Int) { | ||
| ones112 := big.NewInt(0) | ||
| for i := 0; i < 112; i++ { | ||
| ones112 = ones112.SetBit(ones112, i, 1) | ||
| // - dataAvailabilityGasPrice: the upper 112 bits (bits 112-223) | ||
| func UnpackGasPrice(packedPrice *big.Int) (executionGasPrice, dataAvailabilityGasPrice *big.Int, err error) { | ||
krebernisak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if packedPrice == nil { | ||
| return nil, nil, ErrNilPackedPrice | ||
| } | ||
| if packedPrice.Sign() < 0 { | ||
| return nil, nil, ErrNegativePackedPrice | ||
| } | ||
| if packedPrice.Cmp(maxUint224) > 0 { | ||
| return nil, nil, ErrPackedPriceExceeds224Bits | ||
| } | ||
|
|
||
| executionGasPrice = new(big.Int).And(packedPrice, ones112) | ||
| executionGasPrice = new(big.Int).And(packedPrice, maxUint112) | ||
| dataAvailabilityGasPrice = new(big.Int).Rsh(packedPrice, 112) | ||
|
|
||
| return executionGasPrice, dataAvailabilityGasPrice | ||
| return executionGasPrice, dataAvailabilityGasPrice, nil | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.