This directory contains the Solana implementation of IBC Eureka protocol, built using the Anchor framework. The programs enable trust-minimized interoperability between Solana and Cosmos SDK chains.
just generate-solana-keypairs <cluster>Where <cluster> is one of: localnet, devnet, testnet, mainnet
This creates keypairs in solana-keypairs/<cluster>/:
access_manager-keypair.jsonics07_tendermint-keypair.jsonics26_router-keypair.jsonics27_gmp-keypair.jsontest_ibc_app-keypair.jsonmock_light_client-keypair.jsondeployer_wallet.json
# Generate a program keypair
solana-keygen new -o solana-keypairs/<cluster>/<program>-keypair.json
# Display the public key (program ID)
solana-keygen pubkey solana-keypairs/<cluster>/<program>-keypair.jsonSecurity Notes:
- Keypairs for
devnet,testnet, andmainnetare automatically gitignored - Only
localnetkeypairs are committed to the repository - Never commit production keypairs to version control
- Store production keypairs securely
Deploy to devnet with a single command:
just deploy-solana devnetThis automatically:
- Builds programs with cluster-specific program IDs
- Deploys all programs to the target cluster
- Updates
Anchor.tomlwith deployed program IDs
# Devnet (free airdrops)
solana airdrop 5 solana-keypairs/devnet/deployer_wallet.json --url devnet
# Testnet
solana airdrop 2 solana-keypairs/testnet/deployer_wallet.json --url testnet
# Mainnet (fund with real SOL)
solana transfer <DEPLOYER_PUBKEY> <AMOUNT> --from <YOUR_WALLET> --url mainnetjust build-solanaThis compiles all programs and generates their IDLs.
cd programs/solana
anchor deploy --provider.cluster <cluster>Or deploy individual programs:
anchor deploy -p access-manager --provider.cluster devnetFor local development and testing:
# Terminal 1: Start local validator
solana-test-validator
# Terminal 2: Configure Solana CLI
solana config set --url localhost
# Terminal 3: Deploy
just deploy-solana localnetanchor deploy -p access-manager --provider.cluster devnet
anchor deploy -p ics26-router --provider.cluster devnet# Build new version
just build-solana
# Deploy upgrade
anchor upgrade target/deploy/ics26_router.so \
--program-id <PROGRAM_ID> \
--provider.cluster devnetNote: After initial deployment, program upgrades should use the AccessManager's upgrade mechanism (see Program Upgradability).
# Check program account
solana program show <PROGRAM_ID> --url devnet
# Verify program executable
solana account <PROGRAM_ID> --url devnet
# Check deployer balance
solana balance solana-keypairs/devnet/deployer_wallet.json --url devnetThe AccessManager provides role-based access control across all IBC programs.
| Role ID | Name | Purpose |
|---|---|---|
0 |
ADMIN_ROLE |
Root administrator with all permissions |
1 |
RELAYER_ROLE |
Submit IBC packets and client updates |
2 |
PAUSER_ROLE |
Pause operations during emergencies |
3 |
UNPAUSER_ROLE |
Resume operations after emergency |
6 |
ID_CUSTOMIZER_ROLE |
Customize client and connection IDs |
u64::MAX |
PUBLIC_ROLE |
Anyone (unrestricted access) |
Note: Role IDs 4, 5 and 7 exist on Ethereum but are not used by any Solana program. The access manager does not restrict which IDs can be granted — consuming programs define and enforce role semantics.
Before granting roles, initialize the AccessManager with an initial admin:
just initialize-access-manager <cluster> <admin-pubkey>Example:
just initialize-access-manager localnet 8ntLtUdGwBaXfFPCrNis9MWsKMdEUYyonwuw7NQwhs5zThis creates the AccessManager PDA and grants ADMIN_ROLE to the specified account.
Grant a role to an account:
just grant-solana-role <cluster> <role-id> <account-pubkey>Example (grant RELAYER_ROLE):
just grant-solana-role localnet 1 8ntLtUdGwBaXfFPCrNis9MWsKMdEUYyonwuw7NQwhs5zRevoke a role from an account:
just revoke-solana-role <cluster> <role-id> <account-pubkey>Example:
just revoke-solana-role localnet 1 8ntLtUdGwBaXfFPCrNis9MWsKMdEUYyonwuw7NQwhs5zPrograms verify roles before executing sensitive operations:
use access_manager::helpers::require_role;
require_role(
&access_manager_account,
roles::RELAYER_ROLE,
&authority_account,
&instructions_sysvar,
&program_id,
)?;Solana programs deployed via BPF Loader Upgradeable can be upgraded by the upgrade authority. We use AccessManager to manage upgrade permissions via role-based access control.
After deploying programs, configure upgrade authority management:
Step 1: Initialize AccessManager (if not already done)
just initialize-access-manager <cluster> <admin-pubkey>Example:
just initialize-access-manager localnet 8ntLtUdGwBaXfFPCrNis9MWsKMdEUYyonwuw7NQwhs5zStep 2: Transfer upgrade authority to AccessManager PDA
just set-upgrade-authority <program-id> <cluster> [current-authority-keypair]Example:
just set-upgrade-authority FRGF7cthWUvDvAHMUARUHFycyUK2VDUtBchmkwrz7hgx localnet ~/.config/solana/id.jsonNotes:
- The upgrade authority PDA is automatically derived with seeds:
["upgrade_authority", program_id] - The third parameter (current authority keypair) is optional - if omitted, the command will tell you which keypair you need
- Use
--skip-new-upgrade-authority-signer-checkis automatically applied since PDAs cannot sign
Once upgrade authority is transferred to AccessManager, upgrades require ADMIN_ROLE.
Execute the entire upgrade process (build, buffer, and upgrade instruction) in one command:
just upgrade-solana-program <program-name> <program-id> <cluster> <upgrader-keypair-path>Example:
just upgrade-solana-program ics26_router 4fMih2CidrXPeRx77kj3QcuBZwREYtxEbXjURUgadoe1 devnet solana-keypairs/devnet/upgrader.jsonThis command automatically:
- Builds the new program version
- Writes bytecode to a buffer account
- Sets buffer authority to the upgrade authority PDA
- Executes the AccessManager.upgrade_program instruction
- Waits for confirmation
Requirements:
- Upgrader keypair must have ADMIN_ROLE
- Deployer wallet must have SOL for buffer creation
- Program must already be deployed with AccessManager as upgrade authority
If you only want to prepare the buffer without executing the upgrade:
just prepare-solana-upgrade <program-name> <cluster> <upgrade-authority-pda>Example:
# Derive the upgrade authority PDA first (seeds: ["upgrade_authority", program_id])
# For ics26-router on devnet:
UPGRADE_AUTH_PDA="<DERIVED_PDA_ADDRESS>"
just prepare-solana-upgrade ics26_router devnet $UPGRADE_AUTH_PDAThis command:
- Builds the new program version
- Writes bytecode to a buffer
- Sets buffer authority to the upgrade authority PDA
- Outputs the buffer address for manual upgrade execution
Step 1: Build new program version
just build-solanaStep 2: Write new bytecode to a buffer
solana program write-buffer programs/solana/target/deploy/<program>.so \
--url <cluster> \
--keypair solana-keypairs/<cluster>/deployer_wallet.json \
--use-rpcThis outputs a buffer address like: Buffer: <BUFFER_ADDRESS>
Step 3: Set buffer authority to match program upgrade authority
solana program set-buffer-authority <BUFFER_ADDRESS> \
--new-buffer-authority <UPGRADE_AUTHORITY_PDA> \
--buffer-authority solana-keypairs/<cluster>/deployer_wallet.json \
--keypair solana-keypairs/<cluster>/deployer_wallet.json \
--url <cluster>After preparing the buffer (using either option above), execute the upgrade instruction.
Prerequisites:
Build the solana-ibc CLI tool if not already built:
go build -o bin/solana-ibc ./tools/solana-ibcUsing solana-ibc CLI:
# First, derive the upgrade authority PDA
UPGRADE_AUTH_PDA=$(bin/solana-ibc upgrade derive-pda <ACCESS_MANAGER_PROGRAM_ID> <TARGET_PROGRAM_ID>)
# Get the program data address
PROGRAM_DATA_ADDR=$(solana program show <TARGET_PROGRAM_ID> --url <CLUSTER_URL> | grep "ProgramData Address" | awk '{print $3}')
# Execute the upgrade
bin/solana-ibc upgrade program \
<CLUSTER_URL> \
<UPGRADER_KEYPAIR_PATH> \
<TARGET_PROGRAM_ID> \
<BUFFER_ADDRESS> \
<ACCESS_MANAGER_PROGRAM_ID> \
$PROGRAM_DATA_ADDRExample:
# For ics26-router on localnet
UPGRADE_AUTH_PDA=$(bin/solana-ibc upgrade derive-pda \
4fMih2CidrXPeRx77kj3QcuBZwREYtxEbXjURUgadoe1 \
FRGF7cthWUvDvAHMUARUHFycyUK2VDUtBchmkwrz7hgx)
PROGRAM_DATA_ADDR=$(solana program show FRGF7cthWUvDvAHMUARUHFycyUK2VDUtBchmkwrz7hgx \
--url http://localhost:8899 | grep "ProgramData Address" | awk '{print $3}')
bin/solana-ibc upgrade program \
http://localhost:8899 \
solana-keypairs/localnet/deployer_wallet.json \
FRGF7cthWUvDvAHMUARUHFycyUK2VDUtBchmkwrz7hgx \
<BUFFER_ADDRESS_FROM_STEP_2> \
4fMih2CidrXPeRx77kj3QcuBZwREYtxEbXjURUgadoe1 \
$PROGRAM_DATA_ADDRNote: The just upgrade-solana-program command (documented above) automates all these steps, including buffer creation, PDA derivation, and upgrade execution. For programmatic integration, see e2e/interchaintestv8/solana_upgrade_test.go for a complete Go implementation example.
Access Control:
- Only accounts with
ADMIN_ROLEcan trigger upgrades - CPI calls to
upgrade_programare permitted only from whitelisted programs such as multisig wallets (viarequire_admin) - Instructions sysvar verification prevents fake sysvar attacks
Authority Verification:
- Buffer authority must match program upgrade authority (BPF Loader requirement)
- Upgrade authority PDA seeds are validated via Anchor constraints
- Program account must be writable and executable
Audit Trail:
- All upgrades emit
ProgramUpgradedEventwith:- Program ID
- Upgrader public key
- Timestamp
To revoke upgrade capability, revoke ADMIN_ROLE from an account:
just revoke-solana-role 0 <ADMIN_PUBKEY> <cluster>Or using the solana-ibc CLI directly:
bin/solana-ibc access-manager revoke \
<CLUSTER_URL> \
<ADMIN_KEYPAIR> \
0 \
<ADMIN_PUBKEY_TO_REVOKE> \
<ACCESS_MANAGER_PROGRAM_ID>Note: Be careful not to revoke the last admin, as this would lock you out of admin operations.
# Build all programs (generates all IDLs)
just build-solana
# Build specific program only (generates only its IDL)
just build-solana ics26-router
# Using anchor directly (from programs/solana directory)
cd programs/solana
anchor build
anchor build -p ics26-router# All Solana tests (unit + integration)
just test-solana
# Specific program tests (requires the app being built)
cargo test --manifest-path programs/solana/programs/ics26-router/Cargo.toml
# E2E tests
just test-e2e-solana Test_Deploy
just test-e2e-solana-gmp Test_GMPCounterFromCosmos
just test-e2e-solana-upgrade Test_ProgramUpgrade_Via_AccessManager# Format code
just fmt-solana
# Run linter
just lint-solanaIDL (Interface Definition Language) files are automatically generated during build:
# Generate IDLs for all programs
just build-solana
# Generate IDL for specific program only
just build-solana ics26-routerIDL files are written to target/idl/ and contain the program's interface definition for client libraries and tools.