Skip to content

Commit

Permalink
CCIP chain selectors implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mateusz-sekara committed Aug 23, 2023
1 parent e05d0c2 commit 8399866
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @smartcontractkit/ccip
20 changes: 20 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Go - Build and test

on: [ push ]

jobs:
build-test:
name: Build and test
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version-file: "go.mod"
cache: false
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@

# Go workspace file
go.work


.idea
.vscode/
*.iml
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 SmartContract

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
# ccip-chain-selectors
# CCIP chain selectors

CCIP uses its own set of chain selectors represented by uint64 to identify blockchains. This repository contains a
mapping between the CCIP chain identifiers (`chainSelectorId`) and the chain identifiers used by the blockchains
themselves (`chainId`).

Please refer to the [official documentation](https://docs.chain.link/ccip/supported-networks) to learn more about
supported networks and their selectors.

### Installation

`go get github.com/smartcontract/ccip-chain-selectors`

### Usage

```go
import (
"github.com/smartcontractkit/ccip-chain-selectors"
)

func main() {
// Getting selector based on ChainId
selector, err := selectors.SelectorFromChainId(420)

// Getting ChainId based on ChainSelector
chainId, err := selectors.ChainIdFromSelector(2664363617261496610)

// Accessing mapping directly
lookupChainId := uint64(1337)
if chainSelector, exists := selectors.EvmChainIdToChainSelector()[lookupChainId]; exists {
fmt.Println("Found chain selector for chain", lookupChainId, ":", chainSelector)
}
}
```

### Contributing

Any new chains and selectors should be always added to [selectors.yml](selectors.yml) and client libraries should load
details from this file. This ensures that all client libraries are in sync and use the same mapping.

If you need a support for a new language, please open a PR with the following changes:
- Library codebase is in a separate directory
- Library uses selectors.yml as a source of truth
- Proper Github workflow is present to make sure code compiles and tests pass
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/smartcontractkit/ccip-chain-selectors

go 1.20

require gopkg.in/yaml.v3 v3.0.1
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
50 changes: 50 additions & 0 deletions selectors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ccip_chain_selectors

import (
_ "embed"
"fmt"

"gopkg.in/yaml.v3"
)

//go:embed selectors.yml
var selectorsYml []byte
var evmChainIdToChainSelector = parseYml()

func parseYml() map[uint64]uint64 {
type ymlData struct {
Selectors map[uint64]uint64 `yaml:"selectors"`
}

var data ymlData
err := yaml.Unmarshal(selectorsYml, &data)
if err != nil {
panic(err)
}

return data.Selectors
}

func EvmChainIdToChainSelector() map[uint64]uint64 {
copyMap := make(map[uint64]uint64, len(evmChainIdToChainSelector))
for k, v := range evmChainIdToChainSelector {
copyMap[k] = v
}
return copyMap
}

func ChainIdFromSelector(chainSelectorId uint64) (uint64, error) {
for k, v := range evmChainIdToChainSelector {
if v == chainSelectorId {
return k, nil
}
}
return 0, fmt.Errorf("chain not found for chain selector %d", chainSelectorId)
}

func SelectorFromChainId(chainId uint64) (uint64, error) {
if chainSelectorId, exist := evmChainIdToChainSelector[chainId]; exist {
return chainSelectorId, nil
}
return 0, fmt.Errorf("chain selector not found for chain %d", chainId)
}
21 changes: 21 additions & 0 deletions selectors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
selectors:
# Testnets
97: 13264668187771770619 # BSC Testnet
420: 2664363617261496610 # Optimism Goerli
1000: 11787463284727550157 # Dev network
1337: 3379446385462418246 # Dev network
2337: 12922642891491394802 # Dev network
43113: 14767482510784806043 # Avalanche Fuji
76578: 781901677223027175
84531: 5790810961207155433 # BASE Goerli
80001: 12532609583862916517 # Polygon Mumbai
421613: 6101244977088475029 # Arbitrum Goerli
11155111: 16015286601757825753 # Sepolia
# Mainnets
1: 5009297550715157269 # Ethereum
10: 3734403246176062136 # Optimism
56: 11344663589394136015 # BSC
137: 4051577828743386545 # Polygon
8453: 15971525489660198786 # BASE
42161: 4949039107694359620 # Arbitrum
43114: 6433500567565415381 # Avalanche
58 changes: 58 additions & 0 deletions selectors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ccip_chain_selectors

import "testing"

func TestEvmChainIdToChainSelectorReturningCopiedMap(t *testing.T) {
selectors := EvmChainIdToChainSelector()
selectors[1] = 2

_, err := ChainIdFromSelector(2)
if err == nil {
t.Error("Changes to map should not affect the original map")
}

_, err = ChainIdFromSelector(1)
if err == nil {
t.Error("Changes to map should not affect the original map")
}
}

func TestChainIdFromSelector(t *testing.T) {
_, err := ChainIdFromSelector(0)
if err == nil {
t.Error("Should return error if chain selector not found")
}

_, err = ChainIdFromSelector(99999999)
if err == nil {
t.Error("Should return error if chain selector not found")
}

chainId, err := ChainIdFromSelector(13264668187771770619)
if err != nil {
t.Error("Should return chain id if chain selector found")
}
if chainId != 97 {
t.Error("Should return correct chain id")
}
}

func TestSelectorFromChainId(t *testing.T) {
_, err := SelectorFromChainId(0)
if err == nil {
t.Error("Should return error if chain not found")
}

_, err = SelectorFromChainId(99999999)
if err == nil {
t.Error("Should return error if chain not found")
}

chainSelectorId, err := SelectorFromChainId(97)
if err != nil {
t.Error("Should return chain selector id if chain found")
}
if chainSelectorId != 13264668187771770619 {
t.Error("Should return correct chain selector id")
}
}

0 comments on commit 8399866

Please sign in to comment.