Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Cross-Chain Fundraising Campaign with Milestone-Based Releases

A technical guide to implementing a fundraising smart contract system that releases funds or tokens across chains only after verifiable project milestones are met.
Chainscore © 2026
introduction
TUTORIAL

Introduction to Cross-Chain Milestone Fundraising

A technical guide to structuring and deploying a fundraising campaign that releases capital across multiple blockchains based on verifiable project milestones.

Cross-chain milestone fundraising is a structured approach where a project raises capital that is escrowed and released incrementally across different blockchain networks as predefined development goals are met. This model addresses key issues in traditional fundraising: it mitigates counterparty risk for backers by preventing a single-point withdrawal of funds, and it incentivizes consistent project delivery for builders. Instead of a one-time token sale or grant disbursement, funds are locked in a programmable smart contract on a primary chain (like Ethereum or Arbitrum) with release triggers connected to verifiable on-chain or off-chain milestones on other chains (such as Polygon, Base, or Solana).

The core technical architecture relies on a combination of oracles and cross-chain messaging protocols. A milestone contract on the funding chain holds the capital. When a project team completes a milestone—such as deploying a core PoolFactory on Optimism or reaching a specific TVL on a testnet—an oracle like Chainlink or a decentralized attestation network (e.g., EAS) submits verifiable proof to the contract. This proof is often relayed via a cross-chain messaging layer like Axelar, LayerZero, or Wormhole, which executes the conditional logic to release the next tranche of funds to the project's wallet on the relevant chain.

Setting up a campaign involves several key steps. First, define clear, objective milestones with deliverables that can be verified on-chain (e.g., contract deployment, transaction volume thresholds) or through trusted attestations. Next, choose the technology stack: a secure escrow contract template (like OpenZeppelin's VestingWallet adapted for milestones), an oracle service for verification, and a cross-chain messaging protocol. Finally, deploy and configure the contracts, linking the funding vault's release conditions to the specific data feeds or events from the target chains. This creates a transparent, trust-minimized framework for both funders and project teams.

For developers, a basic Solidity escrow contract might inherit from a cross-chain-enabled base. The contract would store funds and include a function like releaseMilestone(uint256 milestoneId, bytes calldata _proof) that can only be called by a verified cross-chain messenger after validating an oracle proof. The proof could be a signature from a pre-approved committee wallet or a response from a Chainlink Any API call confirming the milestone data. The released funds can be sent natively or bridged to the destination chain using the same messaging layer's token transfer capabilities.

This model is particularly effective for multi-chain dApps, Layer 2 rollup deployments, and cross-chain infrastructure projects. It allows teams to raise capital for a holistic multi-chain roadmap while giving backers confidence that funds are used for intended, verifiable progress. As the interoperability stack matures with protocols like Chainlink CCIP and Polygon CDK, setting up such campaigns is becoming more accessible, enabling a new paradigm of accountable, cross-chain development funding.

prerequisites
TECHNICAL FOUNDATION

Prerequisites and Tech Stack

The technical setup for a secure, cross-chain fundraising campaign requires specific tools, accounts, and smart contract knowledge. This guide outlines the essential components you'll need before deployment.

To build a cross-chain, milestone-based fundraising campaign, you must first establish a secure development environment. This includes installing Node.js (v18 or later) and a package manager like npm or yarn. You will need a code editor such as VS Code and a terminal for command-line operations. The core of your project will be a smart contract development framework; Hardhat or Foundry are the industry standards for writing, testing, and deploying EVM-compatible contracts. These frameworks provide local blockchain networks (e.g., Hardhat Network) for rapid iteration.

Your campaign's logic will reside in smart contracts. You must have a working knowledge of Solidity (v0.8.x) for writing the core vault and milestone logic. Key concepts include access control with OpenZeppelin's Ownable or AccessControl libraries, secure state management, and event emission. You will also need to understand how to interact with oracles like Chainlink for verifiable off-chain data (e.g., proof-of-milestone completion) and cross-chain messaging protocols such as Axelar, LayerZero, or Wormhole for fund distribution across chains.

For testing and deployment, you will require cryptocurrency for gas fees. Obtain test ETH on Sepolia or Goerli, MATIC on Polygon Mumbai, and other native tokens for your target chains. Use a wallet like MetaMask to manage these accounts. You must also secure API keys from blockchain infrastructure providers. An Alchemy or Infura RPC endpoint is essential for connecting to live networks, and you'll need an Etherscan API key for contract verification, which is critical for transparency and user trust.

Finally, plan your project's architecture. A typical stack includes: a smart contract suite (main vault, milestone manager), a frontend client (using React with ethers.js or viem), and backend services for listening to on-chain events. You will integrate IPFS (via Pinata or web3.storage) for storing milestone specifications and proofs in a decentralized manner. Ensure you have a version control system like Git initialized and a clear understanding of the deployment workflow, from local testing to mainnet launch on multiple chains.

system-architecture
ARCHITECTURE GUIDE

Setting Up a Cross-Chain Fundraising Campaign with Milestone-Based Releases

This guide outlines the system architecture for a secure, multi-chain fundraising platform that releases funds to project teams based on verifiable milestone completion.

A cross-chain fundraising campaign with milestone releases requires a modular architecture that separates the fundraising logic from the asset custody and release mechanisms. The core system comprises three primary smart contracts: a Campaign Factory deployed on a primary chain (e.g., Ethereum or Arbitrum), individual Campaign Vaults that hold the raised funds, and a Milestone Oracle or verification module. The factory contract standardizes deployment, while each vault is an isolated instance managing a single project's treasury and release schedule. This separation of concerns enhances security and allows for independent upgrades to the verification logic without affecting live campaigns.

Funds are raised in a multi-asset, multi-chain environment. Contributors can deposit assets like ETH, USDC, or wBTC from various supported networks. A canonical cross-chain messaging protocol like Axelar's General Message Passing (GMP), LayerZero, or Wormhole is integrated to lock/burn assets on the source chain and mint representations on the campaign's host chain. The vault contract holds these bridged assets, ensuring all funds are custodied in a single, auditable location. This design simplifies the release logic and provides a unified view of the campaign's treasury, regardless of the original contribution source.

Milestone verification is the most critical component. The system does not rely on a single centralized admin. Instead, it uses a decentralized attestation model. Options include a committee of KYC'd experts using a multi-sig, a vote by the campaign's own token holders (if applicable), or integration with a verifiable compute oracle like Chainlink Functions to confirm off-chain deliverables. The releaseFunds(milestone_id) function in the vault contract checks the pre-defined conditions and requires a valid proof from the designated verifier before transferring the allocated amount to the project team's wallet.

The architecture must account for failed milestones and refunds. Each campaign vault includes a refund mechanism that allows contributors to reclaim a proportional share of the remaining treasury if a milestone deadline passes without successful verification. This is typically implemented as a time-locked function that switches the vault state from "active" to "refund." Security audits for the vault, the cross-chain token bridges, and the oracle integration are non-negotiable, as funds are locked for extended periods. Using established, audited libraries like OpenZeppelin for access control and pausable functions is essential.

From a developer's perspective, the factory contract simplifies deployment. A project founder calls createCampaign() with parameters including the funding goal, milestone payout schedule (e.g., [30%, 40%, 30%]), verifier address, and token acceptance list. An event emits the new vault address, which is then used for all subsequent interactions. Front-end applications can index these events to display live campaigns. The entire system's state is transparent and verifiable on-chain, providing trustless assurance to both contributors and builders about the rules governing the funds.

key-concepts
CROSS-CHAIN FUNDRAISING

Core Technical Concepts

Technical foundations for building a secure, multi-chain fundraising campaign with automated, trust-minimized milestone releases.

06

Example Stack: Ethereum + Arbitrum Campaign

A practical architecture for a dual-chain campaign:

  1. Settlement Chain: Ethereum Mainnet. Hosts the main milestone escrow contract (Escrow.sol).
  2. Fundraising Chain: Arbitrum One. Hosts a deposit contract (DepositArb.sol).
  3. Flow:
    • Backers deposit ETH or USDC on Arbitrum into DepositArb.sol.
    • The deposit contract locks tokens and sends a message via LayerZero to Escrow.sol on Ethereum, incrementing the total raised.
    • The project team submits milestone proofs to the Ethereum Escrow.sol.
    • Upon approval, Escrow.sol releases native ETH/USDC on Ethereum to the team.
  4. Tools: Foundry for development, OpenZeppelin for contracts, LayerZero's lzApp template, and Tenderly for monitoring.
< 3 min
LayerZero Message Time (Ethereum<>Arbitrum)
$0.10 - $1.50
Estimated Gas Cost per Message
VERIFICATION MECHANISMS

Milestone Verification Method Comparison

Comparison of methods for verifying campaign milestones to trigger cross-chain fund releases.

Verification FeatureMulti-Sig CommitteeOracle-BasedOn-Chain Proof

Verification Trigger

Manual multi-signature vote

Off-chain API data feed

On-chain event or state proof

Time to Verification

1-7 days

< 1 hour

~12 seconds

Decentralization

Semi-decentralized

Centralized (oracle operator)

Fully decentralized

Developer Overhead

High (manage signers)

Medium (integrate oracle)

Low (emit standard events)

Typical Gas Cost

$50-200 per vote

$5-20 per update

$2-10 per proof

Censorship Resistance

Medium

Low

High

Suitable For

High-value, subjective goals

Objective, data-driven goals

On-chain, verifiable actions

AUDIENCE-SPECIFIC GUIDES

Implementation Steps

Campaign Planning and Setup

Define your milestones as clear, verifiable deliverables (e.g., "Complete smart contract audit report from Halborn," "Launch MVP with 1,000 active users"). Each milestone should have a specific funding release amount attached.

Choose your chains. Select a primary chain for fundraising (e.g., Ethereum mainnet for broad access) and the destination chain(s) for development and treasury deployment (e.g., Arbitrum for lower fees).

Select a bridge solution. For non-technical teams, use a UI-based bridge like LayerZero's Stargate or Axelar's Satellite. These allow you to transfer raised funds cross-chain through a web interface without writing code. Ensure the bridge supports both your fundraising and destination chain assets (e.g., USDC, ETH).

Deploy the escrow contract. Use a no-code platform like OpenZeppelin Defender to deploy and manage a pre-audited, milestone-based escrow contract template. Configure the contract with your wallet addresses, milestone criteria, and release amounts.

milestone-contract-code
GUIDE

Setting Up a Cross-Chain Fundraising Campaign with Milestone-Based Releases

This guide explains how to build and deploy a smart contract that securely manages a fundraising campaign, releasing funds to a project team only upon the completion of predefined, verifiable milestones.

A milestone manager contract is a specialized escrow smart contract that automates the release of funds based on objective criteria. Instead of sending the entire raised amount to a project team upfront, the capital is locked in the contract. Funds are only disbursed when the team submits proof that a specific project milestone has been met, and this proof is verified, often by a designated approver or an oracle. This model aligns incentives, reduces counterparty risk for backers, and provides a transparent, trust-minimized framework for project execution, commonly used in grant programs, DAO funding, and startup fundraising.

The core logic of the contract revolves around state management and access control. You will define a Campaign struct containing key parameters: the total fundingGoal, the beneficiary address (the project team), an approver address (e.g., a DAO multisig or grant committee), and an array of Milestone structs. Each milestone should have a description, a payoutAmount, and a completed boolean flag. The contract's state machine typically moves from Funding to Active once the goal is met, to Completed when all milestones are paid, or to Canceled if the campaign is terminated.

Here is a simplified Solidity code snippet outlining the contract structure and a critical function:

solidity
struct Milestone {
    string description;
    uint256 payoutAmount;
    bool completed;
}

struct Campaign {
    address beneficiary;
    address approver;
    uint256 fundingGoal;
    uint256 totalRaised;
    Milestone[] milestones;
    bool isActive;
}

function submitMilestoneCompletion(uint256 _milestoneIndex) external {
    require(msg.sender == campaign.beneficiary, "Not beneficiary");
    require(!campaign.milestones[_milestoneIndex].completed, "Already completed");
    // In practice, you would hash and store IPFS CID of proof here
    emit MilestoneSubmitted(_milestoneIndex, proofCid);
}

function approveMilestone(uint256 _milestoneIndex) external {
    require(msg.sender == campaign.approver, "Not approver");
    Milestone storage milestone = campaign.milestones[_milestoneIndex];
    require(!milestone.completed, "Already paid");
    
    milestone.completed = true;
    (bool success, ) = campaign.beneficiary.call{value: milestone.payoutAmount}("");
    require(success, "Transfer failed");
    emit MilestoneApproved(_milestoneIndex, milestone.payoutAmount);
}

For a campaign to be truly cross-chain, you must integrate a cross-chain messaging protocol like Axelar, LayerZero, or Wormhole. The contract deployed on the fundraising chain (e.g., Ethereum) becomes the source chain app. When a milestone is approved, instead of executing a simple transfer, it sends a cross-chain message to a sibling contract on the destination chain (e.g., Arbitrum or Polygon) where the funds are actually held. The message instructs the destination contract to release the specific payoutAmount to the beneficiary's address on that chain. This separates the logic layer from the asset layer, enabling fundraising in one asset (like ETH) and payouts in another (like USDC on a different chain).

Security is paramount. Key considerations include: reentrancy guards on payout functions, proper access control using modifiers like onlyApprover, validation of milestone indices to prevent out-of-bounds errors, and a robust cancellation/refund mechanism for backers if the campaign fails to meet its goal. For proof submission, avoid storing large files on-chain. Instead, store a hash (like an IPFS Content Identifier or CID) of the off-chain deliverable (report, code commit hash, etc.). The approver verifies the proof off-chain before calling the approveMilestone function.

To deploy, use a development framework like Hardhat or Foundry. Write comprehensive tests simulating the full lifecycle: contributions, milestone submissions by the beneficiary, approvals by the approver, and failed state transitions. After testing on a local fork or testnet, deploy the verified contract to your mainnet of choice. Frontend integration involves connecting a wallet, reading the contract state (goal, raised amount, milestone status), and providing interfaces for backers to contribute and for the beneficiary/approver to manage milestones. This creates a fully functional, transparent, and secure cross-chain fundraising platform.

cross-chain-integration
TUTORIAL

Setting Up a Cross-Chain Fundraising Campaign with Milestone-Based Releases

Learn how to build a secure, multi-chain fundraising contract that releases funds to project teams only after verifiable on-chain milestones are met.

Milestone-based fundraising solves a core problem in Web3: aligning incentives between backers and builders. Instead of releasing a lump sum, funds are locked in a smart contract and disbursed incrementally as the project team completes predefined objectives. This model, popularized by platforms like Gitcoin Grants, reduces risk for contributors and ensures accountability for developers. Implementing this across multiple blockchains allows you to tap into broader liquidity pools and communities, but requires a secure cross-chain messaging layer to coordinate state and trigger payments.

The technical architecture relies on a cross-chain messaging protocol like Axelar, Wormhole, or LayerZero. Your core contract will be deployed on a primary chain (e.g., Ethereum mainnet for maximum security of locked funds). Separate milestone manager contracts are deployed on other chains (e.g., Arbitrum, Polygon) where development activity occurs. When a milestone is verified on a secondary chain, a cross-chain message is sent to the main contract to authorize a fund release. This keeps the bulk of the capital secure while enabling permissionless verification from any connected chain.

Start by defining the campaign parameters in your main CrossChainMilestoneVault.sol contract. Key state variables include the total fundsLocked, the beneficiary address (project team), an array of Milestone structs (each with an amount, description, and bool isReleased), and the address of your chosen General Message Passing (GMP) router. The contract should implement functions to createMilestones() (callable only by the owner), releaseMilestone(uint256 milestoneId) (callable only by the GMP router after verification), and withdrawFunds() for the beneficiary to claim released amounts.

On the secondary chain, deploy a lightweight MilestoneVerifier.sol contract. Its job is to hold the logic for proving a milestone is complete. This could be as simple as checking a specific transaction hash, verifying an NFT was minted, or confirming a contract was deployed. Once the condition is met, anyone (or a designated oracle) can call verifyAndForward(uint256 milestoneId) on the verifier. This function will call the GMP router's send() method with a payload destined for the main vault, instructing it to release the specified milestone.

Here's a simplified code snippet for the release function on the main vault, secured via GMP:

solidity
function executeMilestoneRelease(
    bytes32 payload
) external onlyGmpRouter {
    (uint256 milestoneId) = abi.decode(payload, (uint256));
    require(milestoneId < milestones.length, "Invalid milestone");
    require(!milestones[milestoneId].isReleased, "Already released");

    milestones[milestoneId].isReleased = true;
    releasedAmount += milestones[milestoneId].amount;

    emit MilestoneReleased(milestoneId, milestones[milestoneId].amount);
}

The onlyGmpRouter modifier ensures only authenticated messages from your cross-chain infrastructure can trigger a payout, which is critical for security.

For production, integrate off-chain monitoring and automation. Use a service like Gelato Network or OpenZeppelin Defender to watch for on-chain events from your verifier contracts and automatically relay the GMP messages. Always conduct thorough audits on both the vault and verifier logic, and consider implementing a timelock or multi-sig for the owner functions. This pattern enables transparent, trust-minimized fundraising that can scale across the entire blockchain ecosystem, connecting capital on one chain with provable progress on another.

CROSS-CHAIN FUNDRAISING

Frequently Asked Questions

Common technical questions and solutions for developers building milestone-based, cross-chain fundraising campaigns using smart contracts.

A typical contract uses a state machine to track campaign phases and a mapping to store approved milestones. The core logic involves:

  • Campaign State: Variables like Funding, Active, Completed, or Canceled.
  • Milestone Struct: Contains amount, description, approved (bool), and paid (bool).
  • Release Function: A releaseFunds(uint milestoneId) function that checks:
    1. The campaign is in the Active state.
    2. The specific milestone is approved but not yet paid.
    3. The contract has sufficient balance.

Only the campaign creator or a designated multisig wallet should be able to approve milestones, while the release function can be permissioned or automated via an oracle.

solidity
function releaseMilestone(uint256 _milestoneId) external onlyOwner {
    require(state == State.Active, "Campaign not active");
    require(milestones[_milestoneId].approved, "Milestone not approved");
    require(!milestones[_milestoneId].paid, "Already paid");
    
    uint256 amount = milestones[_milestoneId].amount;
    require(address(this).balance >= amount, "Insufficient funds");
    
    milestones[_milestoneId].paid = true;
    payable(creator).transfer(amount);
}
security-considerations
CROSS-CHAIN FUNDRAISING

Security Considerations and Audits

Implementing secure, milestone-based fund releases across multiple blockchains requires a multi-layered approach to mitigate smart contract and operational risks.

The primary security challenge in cross-chain fundraising is the trustless execution of milestone verification. Unlike a single-chain escrow, funds are locked in a smart contract on the source chain (e.g., Ethereum), while verification logic for releasing funds to a destination chain (e.g., Arbitrum) depends on external data. This creates critical attack vectors: a compromised oracle (like Chainlink) providing false milestone completion data, or a vulnerability in the cross-chain messaging protocol (like LayerZero or Axelar) that could spoof a release message. Your security model must assume the bridging layer itself could be malicious.

Your smart contract architecture must enforce strict access controls and time-locks. Use a multi-signature wallet or a DAO-governed timelock contract as the owner of the fundraiser contract. This prevents a single point of failure from triggering unauthorized releases. Implement a clear dispute resolution period after a milestone is marked complete, allowing contributors to challenge the verification before funds are irreversibly bridged. Code this as a mandatory waiting period, such as a 72-hour window, within the release function logic.

Undergo multiple, specialized audits before deployment. Engage one firm to audit the core milestone escrow logic and another to review the cross-chain integration and oracle usage. For projects using generalized messaging, auditors should examine the application's security context within the protocol, ensuring your contract validates message authenticity and source chain origin. Share the audit reports publicly to build trust. Additionally, consider a bug bounty program on platforms like Immunefi, offering significant rewards for vulnerabilities discovered in the live contract, which can catch issues audits may miss.

Operational security is equally critical. The private keys for the multi-sig signers must be stored in hardware wallets with geographic distribution among trusted team members or legal entities. Document and test your incident response plan for scenarios like a halted bridge or a disputed milestone. Use monitoring tools like Tenderly or OpenZeppelin Defender to set up alerts for contract events and failed transactions, enabling rapid response to suspicious activity across all connected chains.

conclusion
IMPLEMENTATION CHECKLIST

Conclusion and Next Steps

You have now configured a secure, cross-chain fundraising campaign with automated milestone-based fund releases. This final section summarizes key takeaways and outlines how to proceed with deployment, monitoring, and scaling.

Your campaign's security and automation are anchored in the interaction between three core smart contracts: the Vault holding funds, the MilestoneManager enforcing release logic, and the CrossChainExecutor handling inter-blockchain communication. Using a modular architecture allows you to upgrade or replace individual components, like switching oracle providers or adjusting quorum thresholds, without a full redeployment. Always conduct a final audit of the integrated system, focusing on the trust assumptions of your chosen bridge/oracle and the access controls on the Vault's releaseFunds function.

For deployment, follow a staged rollout on testnets. First, deploy and verify your contracts on a testnet for each chain in your campaign (e.g., Sepolia, Arbitrum Sepolia, Base Sepolia). Fund the Vault with test tokens and execute the full workflow: propose a milestone, have the committee vote via the MilestoneManager, and observe the CrossChainExecutor triggering the release. Use block explorers like Etherscan and tools like Tenderly to monitor the cross-chain message lifecycle, ensuring payloads are delivered and executed correctly before moving to mainnet.

Post-launch, operational transparency is critical. Provide backers with a dashboard displaying: real-time Vault balances, milestone status, committee vote tallies, and transaction hashes for all releases. Consider implementing Sentry or OpenZeppelin Defender for smart contract monitoring and alerting. For scaling, you can generalize the MilestoneManager into a factory contract to launch multiple, independent campaigns from a single codebase, or integrate with Safe{Wallet} for more sophisticated multi-signature governance on the committee's actions.

The next logical step is to explore advanced conditional logic. Instead of simple majority votes, you could implement bonded commitments where committee members stake tokens that are slashed for malicious votes, or automated KYC/AML checks via oracle services like Chainlink Functions before a release is approved. To deepen your understanding, review the security considerations in the Chainlink CCIP documentation and analyze real-world implementations like Axelar's General Message Passing to compare cross-chain design patterns.

How to Set Up a Cross-Chain Milestone Fundraising Campaign | ChainScore Guides