Skip to content

[NONEVM-2651] Fix contract versioning#218

Merged
nicolasgnr merged 10 commits into
mainfrom
feat/contract-versioning
Sep 26, 2025
Merged

[NONEVM-2651] Fix contract versioning#218
nicolasgnr merged 10 commits into
mainfrom
feat/contract-versioning

Conversation

@patricios-space
Copy link
Copy Markdown
Collaborator

@patricios-space patricios-space commented Sep 26, 2025

NONEVM-2651

  • Add IDs to the storage of every CCIP contract to enable for multiple deployments
  • Enforce change in type and version for every contract change
  • Return code and code hash in all CCIP contracts

@patricios-space patricios-space changed the title Fix contract versioning [NONEVM-2651] Fix contract versioning Sep 26, 2025
Comment thread .github/workflows/contract-version-check.yml Fixed
Comment on lines +45 to +76
name: Verify Contract Version Updates
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'

steps:
- name: Check out PR code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
path: "pr-branch"

- name: Check out base branch code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
ref: ${{ github.event.pull_request.base.sha }}
path: "base-branch"

- name: Set up Python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: "3.9"

- name: Install Nix
uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31
with:
nix_path: nixpkgs=channel:nixos-unstable

- name: Check contract versions
run: |
pr-branch/.github/scripts/check-contract-versions.py \
--pr-dir pr-branch \
--base-dir base-branch \
--verbose

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 8 months ago

To fix the problem, add a permissions block to the workflow or directly within the check-contract-versions job, specifying the least required privileges. Since none of the steps in the workflow (and particularly the check-contract-versions job) require write access to repository contents or GitHub APIs, you should set contents: read as a minimal and safe default. You can add a top-level permissions block if all jobs require only read access, but to minimize changes and adhere closely to CodeQL's recommendation, add permissions: contents: read to the check-contract-versions job. This change should be made within the .github/workflows/contracts-build.yml file, at the appropriate indentation level so that the permissions block is a sibling to runs-on.


Suggested changeset 1
.github/workflows/contracts-build.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/contracts-build.yml b/.github/workflows/contracts-build.yml
--- a/.github/workflows/contracts-build.yml
+++ b/.github/workflows/contracts-build.yml
@@ -44,6 +44,8 @@
   check-contract-versions:
     name: Verify Contract Version Updates
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     if: github.event_name == 'pull_request'
 
     steps:
EOF
@@ -44,6 +44,8 @@
check-contract-versions:
name: Verify Contract Version Updates
runs-on: ubuntu-latest
permissions:
contents: read
if: github.event_name == 'pull_request'

steps:
Copilot is powered by AI and may make mistakes. Always verify output.
@patricios-space patricios-space marked this pull request as ready for review September 26, 2025 19:28
@patricios-space patricios-space requested a review from a team as a code owner September 26, 2025 19:28
Copilot AI review requested due to automatic review settings September 26, 2025 19:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements comprehensive contract versioning for CCIP contracts by adding unique IDs to enable multiple deployments and enforcing version updates when contracts change.

Key changes:

  • Added ID field to all CCIP contract storage structures to support multiple deployments
  • Implemented automated version enforcement through bytecode comparison in CI/CD
  • Added code and codeHash getter methods to all contracts for better introspection

Reviewed Changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/.core_version Updates core version hash reference
pkg/ccip/bindings/*/*.go Adds ID field to Go binding structs for all CCIP contracts
deployment/ccip/**/*.go Updates deployment operations to include contract IDs
contracts/wrappers/ccip/*.ts Adds ID field to TypeScript contract wrappers
contracts/contracts/**/*.tolk Adds ID field, CONTRACT_VERSION constant, and code/codeHash getters to Tolk contracts
contracts/tests/**/*.ts Updates test data to include ID fields
.github/workflows/contracts-build.yml Adds CI job for contract version validation
.github/scripts/check-contract-versions*.py Implements automated contract version checking scripts
Comments suppressed due to low confidence (1)

.github/scripts/check-contract-versions-old.py:1

  • The code is duplicated with very similar violation creation logic in multiple places. Consider extracting this into a helper function to reduce code duplication and improve maintainability.
#!/usr/bin/env python3

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

)
return result
except subprocess.CalledProcessError as e:
print(f"Command failed in {cwd}: {' '.join(cmd) if isinstance(cmd, list) else cmd}")
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message formatting will fail when cmd is a string because it tries to join a string character by character. The condition should check the type before attempting to join.

Suggested change
print(f"Command failed in {cwd}: {' '.join(cmd) if isinstance(cmd, list) else cmd}")
print(f"Command failed in {cwd}: {' '.join(cmd) if isinstance(cmd, (list, tuple)) else cmd}")

Copilot uses AI. Check for mistakes.
Comment thread scripts/.core_version
Comment on lines +61 to +64
- name: Set up Python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: "3.9"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much additional time will this add to the build? I know Python can be fun to work with, but have we considered using Go?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 re: Python - this could have been just a bash script. It should be ok to use Python for scripting (vs. bash), but we can improve the packaging and setup here by adding the Python env dependencies to Nix vs. having custom local setup and GHA actions/setup-python.

Copy link
Copy Markdown
Collaborator

@nicolasgnr nicolasgnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

My only concern is the potential overhead Python may add to the overall pipeline execution time, as well as the approach to determining changes. While using bytecode differences is likely the most accurate method, it may also be more expensive than some simpler implementations. We can always reconsider this approach if needed and propose an alternative solution in the near future

@nicolasgnr nicolasgnr enabled auto-merge (squash) September 26, 2025 23:04
@nicolasgnr nicolasgnr merged commit 96c13ca into main Sep 26, 2025
29 checks passed
@nicolasgnr nicolasgnr deleted the feat/contract-versioning branch September 26, 2025 23:06
Comment on lines +61 to +64
- name: Set up Python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with:
python-version: "3.9"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 re: Python - this could have been just a bash script. It should be ok to use Python for scripting (vs. bash), but we can improve the packaging and setup here by adding the Python env dependencies to Nix vs. having custom local setup and GHA actions/setup-python.

import "../lib/utils";
import "../lib/access/access_control";

const CONTRACT_VERSION = "0.0.1";
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This CONTRACT_VERSION label now becomes a magic string and needs some underlying understanding how to use/break. Maybe using an explicit lint tag in a comment would help.

Suggested change
const CONTRACT_VERSION = "0.0.1";
///lint:bytecode-version-check
const MY_VERSION_CONST = "0.0.1";

}

// Returns the sha256 hash of the current code of the contract.
get fun codeHash(): int {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we now require adding these getters to all contracts? Isn't this redundant functionality to be hosted in the contracts and the info (code) can easily be sourced by a client (form an compiled artifact or address)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants