Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .cursor/rules/futarchy-project-overview.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ This is a Solana-based futarchy platform that implements decision markets and DA
- Programs follow Anchor's instruction-based architecture

### Testing Patterns
- Tests use `bankrun` for fast, deterministic testing
- Tests run in-process on LiteSVM (via `tests/litesvm/`) for fast, deterministic testing
- Complex transactions use lookup tables and `TransactionMessage` for large account lists
- Tests often require full proposal lifecycle setup (draft → stake → initialize → crank → finalize).
We generally do that setup in `before` and `beforeEach` blocks
Expand Down
23 changes: 13 additions & 10 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
# is released on GitHub.
#

FROM rust:1.75
FROM rust:1.95

ARG DEBIAN_FRONTEND=noninteractive

ARG SOLANA_CLI="1.17.16"
ARG ANCHOR_CLI="0.29.0"
ARG NODE_VERSION="v18.16.0"
ARG SOLANA_CLI="4.3.0"
ARG CARGO_BUILD_SBF="4.4.0"
ARG ANCHOR_CLI="0.32.2"
ARG NODE_VERSION="v20.18.0"

ENV HOME="/root"
ENV PATH="${HOME}/.cargo/bin:${PATH}"
# The cargo bin directory comes first so the standalone cargo-build-sbf wins over the copy Agave bundles.
ENV PATH="${HOME}/.local/share/solana/install/active_release/bin:${PATH}"
ENV PATH="${HOME}/.cargo/bin:${PATH}"
ENV PATH="${HOME}/.nvm/versions/node/${NODE_VERSION}/bin:${PATH}"

# Install base utilities.
Expand All @@ -26,10 +28,8 @@ RUN mkdir -p /workdir && mkdir -p /tmp && \
#RUN wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
#RUN dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb

# Install rust.
RUN curl "https://sh.rustup.rs" -sfo rustup.sh && \
sh rustup.sh -y && \
rustup component add rustfmt clippy
# The base image ships the Rust version rust-toolchain.toml pins; add its components.
RUN rustup component add rustfmt clippy

# Install node / npm / yarn.
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
Expand All @@ -41,7 +41,10 @@ RUN . $NVM_DIR/nvm.sh && \
npm install -g yarn

# Install Solana tools.
RUN sh -c "$(curl -sSfL https://release.solana.com/v${SOLANA_CLI}/install)"
RUN sh -c "$(curl -sSfL https://release.anza.xyz/v${SOLANA_CLI}/install)"

# Install the standalone cargo-build-sbf, which emits SBPFv3 by default.
RUN cargo install cargo-build-sbf --version ${CARGO_BUILD_SBF} --locked

# Install anchor.
RUN cargo install --git https://github.com/coral-xyz/anchor avm --locked --force
Expand Down
28 changes: 11 additions & 17 deletions .github/actions/anchor-test/action.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
name: 'Anchor Test'
description: 'An "anchor test" action that runs in ~1 minute.'
description: 'Build the programs as SBPFv3 and run the test suite.'
branding:
icon: anchor
color: blue
inputs:
node-version:
description: 'Version of node.js to use'
required: false
default: '20.11.0' # LTS
default: '24.22.1'
solana-cli-version:
description: 'Version of Solana CLI to use'
description: 'Version of the Agave CLI to use'
required: false
default: '1.17.16' # stable
default: '4.3.0'
anchor-version:
description: 'Version of Anchor to use'
description: 'Version of the Anchor CLI to use'
required: false
default: '0.29.0' # latest
default: '0.32.2'
features:
description: 'Features to pass to cargo'
required: false
default: 'default'
runs:
using: 'composite'
steps:
- uses: metadaoproject/setup-anchor@aeeb5505f3fd3d52a1080d14863c6aa428c9fdf9 # v3.4
- uses: ./.github/actions/setup-toolchain
with:
node-version: ${{ inputs.node-version }}
solana-cli-version: ${{ inputs.solana-cli-version }}
Expand All @@ -39,17 +39,11 @@ runs:
- name: Create keypair
run: solana-keygen new --no-bip39-passphrase
shell: bash
- name: Make Anchor.toml compatible with runner
run: sed -i 's:/user/:/runner/:' Anchor.toml
shell: bash
- name: Install Cargo toolchain
uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # v1.0.7
with:
toolchain: stable
profile: minimal
components: rustc
- name: Cache Cargo dependencies
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: Build programs
run: anchor build -- --features ${{ inputs.features }}
shell: bash
- name: Run tests
run: anchor test -- --features ${{ inputs.features }}
run: anchor test --skip-build
shell: bash
67 changes: 67 additions & 0 deletions .github/actions/setup-toolchain/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: 'Setup Toolchain'
description: 'Install Node.js, the Rust version pinned in rust-toolchain.toml, the Agave CLI, the Anchor CLI and the standalone cargo-build-sbf.'
inputs:
node-version:
description: 'Version of Node.js to use'
required: false
default: '24.22.1'
solana-cli-version:
description: 'Version of the Agave CLI to use'
required: false
default: '4.3.0'
anchor-version:
description: 'Version of the Anchor CLI to use'
required: false
default: '0.32.2'
cargo-build-sbf-version:
description: 'Version of the standalone cargo-build-sbf to use'
required: false
default: '4.4.0'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
# Installs the Rust version pinned in rust-toolchain.toml.
- name: Install Rust
run: rustup toolchain install
shell: bash
- name: Cache Agave CLI
uses: actions/cache@v4
id: cache-agave
with:
path: ~/.local/share/solana/
key: agave-${{ runner.os }}-${{ inputs.solana-cli-version }}
- name: Install Agave CLI
if: steps.cache-agave.outputs.cache-hit != 'true'
run: sh -c "$(curl -sSfL https://release.anza.xyz/v${{ inputs.solana-cli-version }}/install)"
shell: bash
- name: Install Anchor CLI
run: npm i -g @anchor-lang/cli@${{ inputs.anchor-version }}
shell: bash
- name: Cache cargo-build-sbf
uses: actions/cache@v4
id: cache-cargo-build-sbf
with:
path: ~/.cargo/bin/cargo-build-sbf
key: cargo-build-sbf-${{ runner.os }}-${{ inputs.cargo-build-sbf-version }}
- name: Install cargo-build-sbf
if: steps.cache-cargo-build-sbf.outputs.cache-hit != 'true'
run: cargo install cargo-build-sbf --version ${{ inputs.cargo-build-sbf-version }} --locked
shell: bash
# Later lines end up earlier on PATH, so the cargo-installed cargo-build-sbf wins over the copy Agave bundles.
- name: Put the toolchain on PATH
run: |
echo "$HOME/.local/share/solana/install/active_release/bin" >> "$GITHUB_PATH"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
shell: bash
- name: Check tool versions
run: |
rustc --version
solana --version
[ "$(anchor --version)" = "anchor-cli ${{ inputs.anchor-version }}" ] ||
{ echo "anchor --version must print anchor-cli ${{ inputs.anchor-version }}"; exit 1; }
[ "$(cargo build-sbf --version | head -1)" = "cargo-build-sbf ${{ inputs.cargo-build-sbf-version }}" ] ||
{ echo "cargo-build-sbf ${{ inputs.cargo-build-sbf-version }} must be the first cargo-build-sbf on PATH"; exit 1; }
shell: bash
2 changes: 2 additions & 0 deletions .github/actions/solana/verify-build/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ runs:
--program-id ${{ inputs.program-id }} \
--url ${{ inputs.rpc-url }} \
--library-name ${{ inputs.program }} \
--arch v3 \
-k ./deploy-keypair.json \
$ARGS \
${{ inputs.repo-url }} \
Expand All @@ -108,6 +109,7 @@ runs:
${{ inputs.repo-url }} \
--program-id ${{ inputs.program-id }} \
--library-name ${{ inputs.program }} \
--arch v3 \
--uploader ${{ inputs.vault-address }} \
--commit-hash ${{ inputs.commit-hash }} \
--url ${{ inputs.rpc-url }} \
Expand Down
61 changes: 19 additions & 42 deletions .github/repo-guard.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,28 @@

[toolchain]
# Anchor CLI version. Consistent across every workflow.
anchor_version = "0.29.0"
anchor_version = "0.32.2"

# Solana CLI declared in Anchor.toml `[toolchain] solana_version`. Local-dev
# only: anchor test on a developer machine auto-installs this version. CI
# workflows pass their own solana-cli-version explicitly and ignore Anchor.toml.
local_dev_solana_version = "1.17.34"
# Solana CLI declared in Anchor.toml `[toolchain] solana_version`. anchor test
# on a developer machine auto-installs this version. CI workflows pass their
# own solana-cli-version explicitly, except `reusable-build.yaml`, which reads
# this same Anchor.toml value.
local_dev_solana_version = "4.3.0"

# Per-workflow Solana CLI versions. The split is intentional:
#
# 1.17.31 - build/test workflows that compile programs locally. This is the
# newest tag published as `ellipsislabs/solana:<ver>` on Docker
# Hub, which is what solana-verify uses to reproduce the deployed
# .so files. Changing this version changes the bytes that
# solana-verify expects, breaking verification of deployed
# programs unless they are rebuilt.
#
# 1.17.16 - CLI tooling workflows. These do not compile - they only invoke
# `solana program write-buffer` / `solana-verify --remote`, which
# talk to the cluster RPC. The version mostly does not matter;
# 1.17.16 is what the repo has used and there is no reason to
# move it.
# Per-workflow Solana CLI versions. Every workflow that compiles programs or
# talks to a cluster runs the Agave 4.3.0 CLI: the artifacts are SBPFv3, which
# a pre-4.x CLI rejects in `solana program write-buffer`. Verifiable builds
# compile inside the solana-verify Docker image, so
# `generate-verifiable-builds.yaml` declares no CLI version.
#
# `reusable-build.yaml` is intentionally not in this map: it reads versions
# from Cargo.lock via `solana-developers/github-actions/extract-versions`,
# so the version is dynamic and stays in sync with the workspace.
# from Anchor.toml `[toolchain]` via
# `solana-developers/github-actions/extract-versions`, so the version stays
# in sync with the workspace.
[toolchain.workflow_solana_cli]
".github/workflows/anchor-test.yaml" = "1.17.31"
".github/workflows/generate-verifiable-builds.yaml" = "1.17.31"
".github/workflows/deploy-buffer.yaml" = "1.17.16"
".github/workflows/verify-build.yaml" = "1.17.16"
".github/workflows/anchor-test.yaml" = "4.3.0"
".github/workflows/deploy-buffer.yaml" = "4.3.0"
".github/workflows/verify-build.yaml" = "4.3.0"

[cargo]
# Every program's Cargo.toml must pin external deps with `=x.y.z`. Loose
Expand All @@ -43,16 +35,8 @@ local_dev_solana_version = "1.17.34"
# anchor-lang and anchor-spl must be the version declared below across
# every program manifest. Cross-program divergence (program A pins =0.29.0
# but program B pins =0.29.1) fails.
anchor_lang_version = "0.29.0"
anchor_spl_version = "0.29.0"

# `solana-program` crate version. Distinct from any of the CLI versions
# above - this is the Solana primitives library that program binaries link
# against, and Cargo.lock is built around it. Currently pinned by the three
# launchpads (v06/v07/v08). The guard fails if any program pins a different
# version. Cargo.lock freshness independently catches drift between this
# pin and the resolved tree.
solana_program_version = "1.17.14"
anchor_lang_version = "0.32.2"
anchor_spl_version = "0.32.2"

# Minimum age in days for a newly pinned crate version. The check is scoped
# to crates whose version differs from the PR base, so unrelated bumps that
Expand All @@ -70,12 +54,6 @@ package_min_age_days = 14
# add it here in a PR that also bumps the workflow reference. CODEOWNERS
# review is required.
[actions.sha_allowlist]
"metadaoproject/anchor-test" = ["876dde6990e0a3d22e1cf1c702b4e4c64aa47d15"] # v2.3
"metadaoproject/anchor-verifiable-build" = ["6d8fc1999ea4b7ff701e8b166903b398741e1c50"] # v0.4
"metadaoproject/setup-anchor" = [
"7d1e9699eb18c33ba5f32f6a9952f0e90515996a", # v3.2
"aeeb5505f3fd3d52a1080d14863c6aa428c9fdf9", # v3.4
]
"nick-fields/retry" = [
"ce71cc2ab81d554ebbe88c79ab5975992d79ba08", # v3
"14672906e672a08bd6eeb15720e9ed3ce869cdd4", # v2
Expand All @@ -85,7 +63,6 @@ package_min_age_days = 14
"EndBug/add-and-commit" = ["a94899bca583c204427a224a7af87c02f9b325d5"] # v9.1.4
"peter-evans/find-comment" = ["3eae4d37986fb5a8592848f6a574fdf654e61f9e"] # v3
"peter-evans/create-or-update-comment" = ["71345be0265236311c031f5c7866368bd1eff043"] # v4
"actions-rs/toolchain" = ["16499b5e05bf2e26879000db0c1d13f7e13fa3af"] # v1.0.7
"Swatinem/rust-cache" = ["6323deb102c322ba6fcbdcafc7e3dddab59af2b6"] # v2.9.2

[sensitive_diff]
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/anchor-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ env:

jobs:
run-anchor-test:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.18.0'
node-version: '24.22.1'
cache: 'yarn'
cache-dependency-path: sdk/yarn.lock

Expand All @@ -39,7 +39,7 @@ jobs:

- uses: ./.github/actions/anchor-test
with:
anchor-version: '0.29.0'
solana-cli-version: '1.17.31'
node-version: '20.18.0'
anchor-version: '0.32.2'
solana-cli-version: '4.3.0'
node-version: '24.22.1'

25 changes: 19 additions & 6 deletions .github/workflows/deploy-buffer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ on:
description: 'Program ID'
required: true
type: string
network:
description: 'Network whose deployer keypair pays for the buffer'
required: true
type: choice
options:
- devnet
- mainnet
default: 'devnet'
rpc_url:
description: 'RPC URL'
required: true
Expand All @@ -25,17 +33,18 @@ on:

jobs:
deploy-buffer:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: metadaoproject/setup-anchor@7d1e9699eb18c33ba5f32f6a9952f0e90515996a # v3.2
- uses: ./.github/actions/setup-toolchain
with:
solana-cli-version: '1.17.16'
anchor-version: '0.29.0'
solana-cli-version: '4.3.0'
anchor-version: '0.32.2'
node-version: '24.22.1'
- run: echo "$DEPLOYER_KEYPAIR" > deployer-keypair.json && chmod 600 deployer-keypair.json
shell: bash
env:
DEPLOYER_KEYPAIR: ${{ secrets.DEPLOYER_KEYPAIR }}
DEPLOYER_KEYPAIR: ${{ inputs.network == 'mainnet' && secrets.MAINNET_DEPLOYER_KEYPAIR || secrets.DEVNET_DEPLOYER_KEYPAIR }}
- run: solana-keygen new -s -o buffer-keypair --no-bip39-passphrase
shell: bash
- name: Deploy Buffer
Expand All @@ -44,4 +53,8 @@ jobs:
timeout_minutes: 30
max_attempts: 10
shell: bash
command: solana program write-buffer --max-sign-attempts 50 --with-compute-unit-price 100 --use-rpc --buffer ./buffer-keypair ./verifiable-builds/${{ inputs.program_name }}.so -u $NETWORK
command: solana program write-buffer --max-sign-attempts 50 --with-compute-unit-price 100 --use-rpc -k ./deployer-keypair.json --buffer ./buffer-keypair ./verifiable-builds/${{ inputs.program_name }}.so -u ${{ inputs.rpc_url }}
- name: Remove deployer keypair
if: always()
run: rm -f deployer-keypair.json
shell: bash
Loading
Loading