Taskmaster Bridge is a multi-chain bridge smart contract built on Solana that enables secure asset transfers between Solana and EVM-compatible chains (Ethereum, Arbitrum, and BSC). The architecture emphasizes security, modularity, and scalability.
- Multi-signature Validation: All inbound transactions require threshold signatures from validators
- Multi-signature Governance: Admin operations require multiple approvals
- Replay Protection: Unique nonce system prevents transaction replay attacks
- Emergency Controls: Circuit breaker mechanism for pause/unpause operations
- Access Control: Role-based permissions using PDA-based account ownership
- Separation of Concerns: Clear separation between state, instructions, and business logic
- Independent Modules: Each instruction type has its own dedicated module
- Reusable Components: Shared utilities in constants and error modules
- Configurable Parameters: Validator and admin thresholds can be adjusted
- Dynamic Management: Validators and admins can be added/removed without redeployment
- Multiple Chains: Architecture supports adding new chains without major changes
- Token Flexibility: Supports both native and wrapped tokens
Central configuration account that stores:
- Authority and references to admin/validator sets
- Fee configuration (basis points and minimum fee)
- Operational status (paused/active)
- Global nonce for transaction ordering
- Statistics (total transactions, total value locked)
Key Methods:
get_next_nonce(): Atomically increments and returns transaction nonceis_operational(): Checks if bridge is active
Manages the validator set for cross-chain verification:
- List of authorized validator public keys
- Threshold for required signatures
- Methods for adding/removing validators
Key Methods:
is_validator(): Check if address is authorizedadd_validator(): Add new validator with duplicate preventionremove_validator(): Remove validator with threshold adjustmentverify_threshold(): Verify signature count meets threshold
Multi-signature governance structure:
- List of admin public keys
- Threshold for admin operations
- Similar structure to ValidatorSet for consistency
Key Methods:
is_admin(): Check admin authorizationadd_admin()/remove_admin(): Manage admin setverify_admin_action(): Verify admin signature threshold
Maps tokens between Solana and external chains:
- Solana token mint address
- External chain ID and token address
- Token type (native vs wrapped)
- Active status flag
- Statistics (total locked, total wrapped)
Key Methods:
is_operational(): Check if pair is activeincrease_locked()/decrease_locked(): Track locked tokensincrease_wrapped()/decrease_wrapped(): Track wrapped tokens
Records all bridge transactions:
- Transaction metadata (nonce, direction, status)
- Chain IDs (source and destination)
- Token and amount information
- External transaction hash for verification
- Validator signatures
- Timestamp
Transaction States:
Pending: Awaiting validator signaturesVerified: Threshold met, ready for executionExecuted: Successfully completedFailed: Transaction failed
Transaction Directions:
Lock: Locking native tokens (Solana → External)Unlock: Unlocking native tokens (External → Solana)MintWrapped: Minting wrapped tokens (External → Solana)BurnWrapped: Burning wrapped tokens (Solana → External)
Sets up the bridge with initial configuration:
- Creates bridge, validator set, and admin set accounts
- Validates initial parameters
- Establishes fee structure
Accounts Created:
- Bridge (PDA)
- ValidatorSet (PDA)
- AdminSet (PDA)
Locks native SPL tokens to bridge to external chain:
- Validates inputs and bridge state
- Calculates and collects fee
- Transfers tokens from user to vault
- Creates executed transaction record
- Updates bridge statistics
Account Flow:
User Token Account → Bridge Vault (amount - fee)
User Token Account → Fee Collector (fee)
Releases locked tokens from external chain:
- Validator initiates with external transaction proof
- Creates pending transaction record
- Other validators call
verify_transactionto add signatures - Once verified,
execute_unlocktransfers tokens to recipient
Multi-phase Process:
Phase 1: Initiate (validator) → Status: Pending
Phase 2: Verify (other validators) → Status: Verified (when threshold met)
Phase 3: Execute (anyone) → Status: Executed
Mints wrapped tokens representing external assets:
- Validator initiates with external transaction proof
- Similar multi-phase verification as unlock
- Mints new wrapped tokens to recipient
Key Feature:
- Bridge has mint authority over wrapped token
- PDA-based minting for security
Burns wrapped tokens to release on external chain:
- Validates and burns wrapped tokens
- Collects fee (in wrapped tokens)
- Creates executed transaction record
Validators sign pending transactions:
- Adds validator signature
- Checks for duplicates
- Updates status to Verified when threshold met
Executes verified unlock transactions:
- Validates transaction is verified
- Transfers tokens from vault using PDA signer
- Updates statistics
- Changes status to Executed
Executes verified mint transactions:
- Validates transaction is verified
- Mints tokens using PDA signer
- Updates statistics
- Changes status to Executed
Emergency circuit breaker:
- Any admin can pause the bridge
- Prevents all bridging operations
- Can be unpaused by admin
Dynamic validator set management:
add_validator: Add new validatorremove_validator: Remove validator (prevents removing last one)update_validator_threshold: Adjust signature requirement- Similar functions for admin management
Register Native Token Pair:
- Creates token pair for existing SPL token
- Creates vault to hold locked tokens
- Vault authority is bridge PDA
Register Wrapped Token Pair:
- Creates new wrapped token mint
- Mint authority is bridge PDA
- Creates token pair mapping
Toggle Token Pair:
- Enable/disable specific token pairs
- Allows granular control without deletion
Configurable fee structure:
- Update percentage fee (basis points)
- Update minimum fee (lamports)
- Update fee collector address
All critical accounts use PDAs with deterministic seeds:
Bridge: ["bridge"]
ValidatorSet: ["validator_set", bridge_pubkey]
AdminSet: ["admin_set", bridge_pubkey]
TokenPair: ["token_pair", bridge_pubkey, mint, chain_id]
BridgeTransaction:["bridge_tx", bridge_pubkey, nonce]
Vault: ["vault", bridge_pubkey, mint]
WrappedMint: ["wrapped_mint", bridge_pubkey, external_addr, chain_id]
// Validator signature verification
pub fn verify_threshold(&self, signers: &[Pubkey]) -> Result<()> {
// Check for duplicates
// Count valid signatures
// Ensure threshold is met
}- Each transaction has unique nonce
- Nonce must match current bridge nonce
- Nonce increments atomically
- Transaction records are permanent
// Admin-only operations
#[account(
constraint = admin_set.is_admin(&admin.key()) @ BridgeError::Unauthorized
)]
pub admin: Signer<'info>,
// Validator-only operations
#[account(
constraint = validator_set.is_validator(&validator.key()) @ BridgeError::Unauthorized
)]
pub validator: Signer<'info>,
// Bridge operational check
#[account(
constraint = bridge.is_operational() @ BridgeError::BridgePaused
)]
pub bridge: Account<'info, Bridge>,// Only allow valid state transitions
match (self.status, new_status) {
(Pending, Verified) => {},
(Verified, Executed) => {},
(Pending | Verified, Failed) => {},
_ => return Err(InvalidTransactionStatus),
}User Action
↓
Lock/Burn on Solana (instant execution)
↓
Transaction Record Created (status: Executed)
↓
Relayer Monitors Solana
↓
Relayer Submits to External Chain
↓
Validators Sign External Transaction
↓
Asset Released on External Chain
External Chain Transaction
↓
Validator Detects
↓
Validator Initiates Unlock/Mint (status: Pending)
↓
Other Validators Monitor
↓
Validators Call verify_transaction (add signatures)
↓
Threshold Met (status: Verified)
↓
Anyone Calls Execute
↓
Tokens Released/Minted (status: Executed)
fn calculate_fee(amount: u64, fee_basis_points: u16, min_fee: u64) -> Result<u64> {
let percentage_fee = (amount * fee_basis_points) / 10000;
Ok(max(percentage_fee, min_fee))
}- Fees collected in the same token being bridged
- Sent to designated fee collector account
- Fee collector can be updated by admins
Custom error codes for all failure scenarios:
BridgePaused: Operations blocked during pauseUnauthorized: Permission deniedInsufficientSignatures: Threshold not metInvalidChainId: Unsupported chainTransactionAlreadyProcessed: Replay attempt- And 20+ more specific errors
- Add chain ID constant to
constants.rs - Update chain ID validation in instructions
- No other code changes required
- Dynamic: Use
add_validatorinstruction - No redeployment needed
- Automatic threshold adjustment on removal
- Unlimited token pairs
- Each pair is independent PDA
- Can be enabled/disabled individually
- Test each instruction handler independently
- Test state transitions
- Test access control
- Test error conditions
- Test complete transaction flows
- Test multi-signature verification
- Test admin operations
- Test edge cases and attack vectors
Before mainnet deployment:
- Internal code review
- External security audit
- Testnet deployment and testing
- Bug bounty program
-
Pre-deployment
- Security audit completed
- All tests passing
- Program ID updated in lib.rs and Anchor.toml
- Initial validators identified
- Initial admins identified
- Fee structure decided
-
Deployment
- Deploy to devnet
- Test all operations on devnet
- Deploy to mainnet-beta
- Initialize bridge with production parameters
-
Post-deployment
- Register initial token pairs
- Set up relayer infrastructure
- Monitor transactions
- Maintain validator set
- Governance Token: Decentralized governance
- Dynamic Fees: Market-based fee adjustment
- Slashing: Penalize malicious validators
- Batching: Batch multiple transactions for efficiency
- Cross-chain Messaging: Support arbitrary data transfer
- Additional Chains: Support more blockchains (Polygon, Avalanche, etc.)
- Use program upgradability carefully
- Consider using proxy pattern for major changes
- Maintain backwards compatibility where possible
- Plan migration strategy for state changes
This architecture provides a secure, scalable, and flexible foundation for cross-chain asset bridging. The modular design allows for easy maintenance and feature additions, while multiple layers of security protect user assets.