Skip to content

Commit 0bf04fb

Browse files
authored
Introduce CCTP Contracts (#1)
# Summary This PR introduces the MessageTransmitterV2, TokenMessengerMinterV2, and CctpForwarder contracts that enable native cross-chain USDC transfers between Stellar and EVM networks via Circle's Cross-Chain Transfer Protocol.
2 parents 8f03ee3 + 8117f8c commit 0bf04fb

133 files changed

Lines changed: 40367 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cargo/config.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[alias]
2+
build-contracts = "build --release --target wasm32v1-none -p message-transmitter-v2 -p token-messenger-minter-v2 -p cctp-forwarder"
3+
cov = "llvm-cov --all-features --workspace --ignore-filename-regex (test.*\\.rs$|.*stablecoin-xlm/.*)"
4+
cov-html = "llvm-cov --all-features --workspace --html --ignore-filename-regex (test.*\\.rs$|.*stablecoin-xlm/.*)"

.githooks/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Git Hooks
2+
3+
This directory contains Git hooks for the Stellar CCTP.
4+
5+
## Setup
6+
7+
To enable these hooks, run the following command from the repository root:
8+
9+
```bash
10+
git config core.hooksPath .githooks
11+
```
12+
13+
Or run this one-liner to set it up:
14+
15+
```bash
16+
chmod +x .githooks/pre-commit && git config core.hooksPath .githooks
17+
```
18+
19+
## Available Hooks
20+
21+
### pre-commit
22+
23+
Runs before each commit to ensure:
24+
- Code is properly formatted (`cargo fmt`)
25+
- No linting issues exist (`cargo clippy`)
26+
27+
The hook automatically runs checks on the Soroban contracts in the `soroban/` directory.
28+
29+
If any check fails, the commit will be blocked until issues are fixed.
30+
31+
## Bypassing Hooks
32+
33+
If you need to bypass hooks in an emergency (not recommended):
34+
35+
```bash
36+
git commit --no-verify
37+
```
38+
39+
## Requirements
40+
41+
These hooks require:
42+
- `rustfmt` - Install with: `rustup component add rustfmt`
43+
- `clippy` - Install with: `rustup component add clippy`
44+
45+
Both are automatically installed if you're using the project's `rust-toolchain.toml` file.
46+

.githooks/pre-commit

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/sh
2+
# Pre-commit hook for Stellar CCTP contracts
3+
# This hook runs format and lint checks before allowing commits
4+
5+
set -e
6+
7+
echo "🔍 Running pre-commit checks..."
8+
9+
# Check if rustfmt is available, install if missing
10+
if ! cargo fmt --version >/dev/null 2>&1; then
11+
echo "📦 rustfmt not found, installing..."
12+
if ! rustup component add rustfmt; then
13+
echo "❌ Failed to install rustfmt"
14+
exit 1
15+
fi
16+
echo "✅ rustfmt installed successfully"
17+
fi
18+
19+
# Check if clippy is available, install if missing
20+
if ! cargo clippy --version >/dev/null 2>&1; then
21+
echo "📦 clippy not found, installing..."
22+
if ! rustup component add clippy; then
23+
echo "❌ Failed to install clippy"
24+
exit 1
25+
fi
26+
echo "✅ clippy installed successfully"
27+
fi
28+
29+
echo "📝 Running cargo fmt..."
30+
if ! cargo fmt -- --check; then
31+
echo "❌ Code formatting check failed!"
32+
echo " Run 'cargo fmt' to fix formatting issues."
33+
exit 1
34+
fi
35+
36+
echo "🔎 Running cargo clippy..."
37+
if ! cargo clippy --all-targets --all-features -- --deny warnings; then
38+
echo "❌ Clippy found issues!"
39+
echo " Fix the issues or run 'cargo clippy --fix' to auto-fix some of them."
40+
exit 1
41+
fi
42+
43+
echo "✅ All pre-commit checks passed!"

.github/pull_request_template.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Summary
2+
3+
## Detail
4+
5+
## Testing
6+
7+
## Documentation
8+
9+
---
10+
11+
**Requested Reviewers:** @mention

.github/workflows/ci.yml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Copyright 2026 Circle Internet Group, Inc. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
name: CI
18+
on:
19+
push:
20+
branches: [master]
21+
pull_request:
22+
23+
concurrency:
24+
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
25+
cancel-in-progress: true
26+
27+
permissions:
28+
pull-requests: write
29+
contents: write
30+
31+
jobs:
32+
rust_build:
33+
name: Rust Build
34+
runs-on: ubuntu-latest
35+
steps:
36+
- name: Check out repository code
37+
uses: actions/checkout@v4
38+
39+
- name: Set up Rust
40+
run: ./scripts/setup-rust.sh
41+
42+
- name: Run format check
43+
run: cargo fmt -- --check
44+
45+
- name: Run clippy
46+
run: cargo clippy --all-targets --all-features -- --deny warnings
47+
48+
- name: Build contracts
49+
run: cargo build-contracts
50+
51+
- name: Cache build artifacts
52+
uses: actions/cache/save@v4
53+
with:
54+
path: target
55+
key: rust-build-${{ github.sha }}
56+
57+
rust_tests:
58+
name: Rust Tests
59+
needs: rust_build
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: Check out repository code
63+
uses: actions/checkout@v4
64+
65+
- name: Set up Rust
66+
run: ./scripts/setup-rust.sh
67+
68+
- name: Restore build cache
69+
uses: actions/cache/restore@v4
70+
with:
71+
path: target
72+
key: rust-build-${{ github.sha }}
73+
fail-on-cache-miss: true
74+
75+
- name: Run tests
76+
run: cargo test
77+
78+
npm_lint:
79+
name: NPM Lint
80+
runs-on: ubuntu-latest
81+
defaults:
82+
run:
83+
working-directory: scripts
84+
steps:
85+
- name: Check out repository code
86+
uses: actions/checkout@v4
87+
with:
88+
submodules: true
89+
90+
- name: Set up Node.js
91+
uses: actions/setup-node@v4
92+
with:
93+
node-version: 20
94+
95+
- name: Enable Corepack
96+
run: corepack enable
97+
98+
- name: Install dependencies
99+
run: yarn install --immutable
100+
101+
- name: Run lint
102+
run: yarn lint
103+
104+
scan:
105+
needs: [rust_tests, npm_lint]
106+
if: github.event_name == 'pull_request'
107+
uses: circlefin/circle-public-github-workflows/.github/workflows/pr-scan.yaml@v1
108+
with:
109+
allow-reciprocal-licenses: false
110+
111+
release-sbom:
112+
needs: [rust_tests, npm_lint]
113+
if: github.event_name == 'push'
114+
uses: circlefin/circle-public-github-workflows/.github/workflows/attach-release-assets.yaml@v1

.github/workflows/coverage.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2026 Circle Internet Group, Inc. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
name: Code Coverage
18+
19+
on:
20+
pull_request:
21+
branches: [master]
22+
push:
23+
branches: [master]
24+
25+
env:
26+
MINIMUM_COVERAGE_PERCENT: 90
27+
28+
permissions:
29+
contents: read
30+
31+
jobs:
32+
coverage:
33+
name: Test Coverage
34+
runs-on: ubuntu-latest
35+
36+
steps:
37+
- name: Checkout code
38+
uses: actions/checkout@v4
39+
40+
- name: Set up Rust
41+
run: ./scripts/setup-rust.sh
42+
43+
- name: Install llvm-tools-preview component
44+
run: rustup component add llvm-tools-preview
45+
46+
- name: Install cargo-llvm-cov
47+
uses: taiki-e/install-action@cargo-llvm-cov
48+
49+
- name: Check coverage threshold
50+
run: |
51+
cargo llvm-cov --all-features --workspace --ignore-filename-regex 'test.*\\.rs$' --fail-under-lines ${{ env.MINIMUM_COVERAGE_PERCENT }}
52+
53+
- name: Generate HTML coverage report for debugging
54+
run: |
55+
cargo llvm-cov --all-features --workspace --ignore-filename-regex 'test.*\\.rs$' --html
56+
if: failure()
57+
58+
- name: Upload HTML report as artifact
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: coverage-report
62+
path: target/llvm-cov/html/
63+
if: failure()

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Rust's output directory
2+
target
3+
4+
# Local settings
5+
.soroban
6+
.stellar
7+
8+
# Test snapshots
9+
test_snapshots/
10+
11+
.DS_Store
12+
13+
node_modules/
14+
dist/
15+
16+
# Environment files (may contain secrets)
17+
.env*
18+
!.env.example

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "scripts/stablecoin-xlm"]
2+
path = scripts/stablecoin-xlm
3+
url = https://github.com/circlefin/stablecoin-xlm.git

.licenseignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Packages with compound licenses that are individually permissive
2+
# These use "X AND Y" license expressions where both X and Y are permissive licenses
3+
4+
# ISC AND MIT
5+
pkg:npm/@bcoe/v8-coverage
6+
pkg:npm/@npmcli/redact
7+
pkg:npm/abbrev
8+
9+
# Apache-2.0 AND MIT
10+
pkg:npm/@pkgjs/parseargs
11+
pkg:npm/unrs-resolver
12+
13+
# BSD-3-Clause AND ISC
14+
pkg:npm/bcrypt-pbkdf
15+
16+
# LicenseRef-scancode-unknown-license-reference AND MIT
17+
pkg:npm/bignumber.js
18+
19+
# BSD-2-Clause AND BSD-3-Clause
20+
pkg:npm/esprima
21+
22+
# CC0-1.0 AND MIT
23+
pkg:npm/lodash
24+
pkg:npm/lodash.camelcase
25+
pkg:npm/type-fest
26+
27+
# LicenseRef-scancode-dco-1.1 AND MIT
28+
pkg:npm/nan
29+
30+
# BSD-3-Clause AND LicenseRef-scancode-protobuf
31+
pkg:npm/protobufjs
32+
33+
# BSD-3-Clause AND MIT
34+
pkg:npm/sha.js
35+
36+
# BSD-2-Clause AND BSD-3-Clause
37+
pkg:npm/uglify-js
38+
39+
# (MIT OR Apache-2.0) AND Unicode-3.0
40+
pkg:cargo/unicode-ident
41+
42+
# Cargo packages with incompatible or unresolvable license identifiers
43+
# soroban-wasmi: actual license is MIT OR Apache-2.0, but Cargo.toml uses legacy "MIT/Apache-2.0" syntax
44+
pkg:cargo/soroban-wasmi@0.31.1-soroban.20.0.1
45+
# wasmparser/wasmparser-nostd: Apache-2.0 WITH LLVM-exception (more permissive than Apache-2.0, not in allowlist)
46+
pkg:cargo/wasmparser@0.116.1
47+
pkg:cargo/wasmparser-nostd@0.100.2
48+
49+
# Packages where the license scanner cannot detect the license from the
50+
# yarn 4 lockfile format. All verified as MIT on npmjs.com.
51+
pkg:npm/aes-js
52+
pkg:npm/gensync

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Changelog
2+
3+
## 1.0.0, Introduce Stellar CCTP (2026-04-17)
4+
5+
- Create Stellar CCTP Soroban smart contracts for cross-chain token transfers

0 commit comments

Comments
 (0)