Skip to content

Tenderly/vnet-github-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tenderly Virtual TestNets CI/CD Infrastructure

GitHub release GitHub marketplace

The Tenderly/vnet-github-action automates provisioning of Virtual TestNets for smart contract CI/CD pipelines. Virtual TestNets are testing and staging infrastructure with built Mainnet State Sync, Unlimited Faucet, Debugger, and Public Block Explorer

This action creates a new Virtual TestNet from your configuration and exposes its RPC URLs through environment variables, enabling automated testing and staging environments for your protocols.

This action enables:

  • Continuous Integration with Hardhat: Run your Hardhat tests against a forked network and use Tenderly debugger and Simulator to fix issues
  • Protocol Staging with Hardhat and Foundry: Deploy and stage your protocols in an isolated, mainnet-like environment
  • Contract Staging with Hardhat and Foundry: Use dedicated Virtual TestNets as staging environments for contract development

Quick Start

This example shows how to fork Ethereum mainnet with a custom chain ID, enable the Public Block Explorer, and keep the testnet state in sync with mainnet.

After the step Setup Virtual TestNet you can access the RPC URL from TENDERLY_TESTNET_ID, TENDERLY_ADMIN_RPC_URL, and TENDERLY_FOUNDRY_VERIFICATION_URL.

Step 1: Get Access key and project name

  1. Get your Tenderly access key and place it in Github Action Secrets under TENDERLY_ACCESS_KEY.
  2. Place the project name and account name in Github Action environment variables under TENDERLY_PROJECT_NAME and TENDERLY_ACCOUNT_NAME respectively.
  3. Create the file .github/workflows/ci.yaml and use the starter action configuration below.
  4. Commit, push, and check your action execution.
name: Smart Contract CI
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Virtual TestNet
        uses: Tenderly/[email protected]
        with:
          mode: CI
          access_key: ${{ secrets.TENDERLY_ACCESS_KEY }}
          project_name: ${{ vars.TENDERLY_PROJECT_NAME }}
          account_name: ${{ vars.TENDERLY_ACCOUNT_NAME }}
          testnet_name: 'CI Test Network'
          network_id: 1
          chain_id: 73571  # Recommended: prefix with 7357 for unique identification to avoid transaction replay attacks
          public_explorer: true 
          verification_visibility: 'src'  # Options: 'abi', 'src', 'bytecode'
          state_sync: true 

Inputs

Name Required Default Description
access_key Yes - Tenderly API Access Key
project_name Yes - Tenderly Project Name
account_name Yes - Tenderly Account Name
testnet_name No 'CI Virtual TestNet' Display name for the Virtual TestNet
network_id Yes 1 Network ID to fork (e.g., 1 for Ethereum mainnet) - integer
chain_id No - Custom chain ID for Virtual TestNet (Recommended: prefix with 7357) - integer
block_number No 'latest' Block number to fork from (must be a hex string, e.g., '0x1234567')
public_explorer No false Enable block explorer for the Virtual TestNet
verification_visibility No 'bytecode' Contract verification type ('abi', 'src', or 'bytecode')
state_sync No false Enable state synchronization with forked network
mode No 'CI' Action mode ('CI' or 'CD') - CI cleans up after completion, CD preserves the Virtual TestNet

Outputs

The action exports several environment variables:

Variable Description
TENDERLY_TESTNET_ID The ID of the created Virtual TestNet
TENDERLY_ADMIN_RPC_URL Admin RPC endpoint URL
TENDERLY_PUBLIC_RPC_URL Public RPC endpoint URL
TENDERLY_FOUNDRY_VERIFICATION_URL URL for Foundry contract verification
TENDERLY_EXPLORER_URL Block explorer URL for the Virtual TestNet

Integration Examples

The following examples demonstrate how to integrate Tenderly Virtual TestNet into your CI/CD pipeline using popular development frameworks. Each example includes both testing and staging deployment stages, with tests running on ephemeral environments and deployments targeting a persistent staging testnet.

Hardhat Pipeline

This sample configuration will:

  • test contracts by deploying them and sending test transactions to an ephemeral Virtual TestNet
  • deploy contracts to the staging Virtual TestNet
  1. Set up your github action using the following starter yaml:
name: Hardhat Pipeline
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Setup Virtual TestNet
        uses: Tenderly/[email protected]
        with:
          access_key: ${{ secrets.TENDERLY_ACCESS_KEY }}
          project_name: ${{ vars.TENDERLY_PROJECT_NAME }}
          account_name: ${{ vars.TENDERLY_ACCOUNT_NAME }}
          network_id: 1
          chain_id: 73571
          public_explorer: true
      
      - name: Install dependencies
        run: npm install
      
      - name: Run Tests
        run: npx hardhat test --network tenderly_ci

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Virtual TestNet
        uses: Tenderly/[email protected]
        with:
          access_key: ${{ secrets.TENDERLY_ACCESS_KEY }}
          project_name: ${{ vars.TENDERLY_PROJECT_NAME }}
          account_name: ${{ vars.TENDERLY_ACCOUNT_NAME }}
          network_id: 1
          chain_id: 73571
          public_explorer: true
          
      - name: Deploy Contracts
        run: npx hardhat run scripts/deploy.js --network tenderly_ci
  1. Extend your hardhat.config.js by adding the following configuration, using the TENDERLY_ADMIN_RPC_URL and TENDERLY_CHAIN_ID:
{
  networks: {
   tenderly_ci: {
     url: process.env.TENDERLY_ADMIN_RPC_URL,
     chainId: parseInt(process.env.TENDERLY_CHAIN_ID)
   }
 },
 tenderly: {
   project: process.env.TENDERLY_PROJECT_NAME,
   username: process.env.TENDERLY_ACCOUNT_NAME,
   accessKey: process.env.TENDERLY_ACCESS_KEY
 }
}

Foundry Pipeline

This pipeline runs tests and deploys verified contracts to a Virtual TestNet. Virtual TestNets provide a persistent environment, making them ideal for staging and integration testing.

name: Foundry Pipeline
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      
      - name: Install Foundry
        uses: foundry-rs/foundry-toolchain@v1
      
      - name: Build and Test
        run: |
          forge build
          forge test -vvv

  deploy:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Virtual TestNet
        uses: Tenderly/[email protected]
        with:
          access_key: ${{ secrets.TENDERLY_ACCESS_KEY }}
          project_name: ${{ vars.TENDERLY_PROJECT_NAME }}
          account_name: ${{ vars.TENDERLY_ACCOUNT_NAME }}
          network_id: 1
          chain_id: 73571
          public_explorer: true

      - name: Install Foundry
        uses: foundry-rs/foundry-toolchain@v1
      
      - name: Foundry Build
        run: |
          forge --version
          forge build --sizes
          
      - name: Deploy Contracts
        env:
          FOUNDRY_ETH_RPC_URL: ${{ env.TENDERLY_PUBLIC_RPC_URL }}
          FOUNDRY_VERIFIER_URL: ${{ env.TENDERLY_FOUNDRY_VERIFICATION_URL }}
        run: |
          forge script script/Deploy.s.sol \
            --rpc-url $FOUNDRY_ETH_RPC_URL \
            --verifier-url $FOUNDRY_VERIFIER_URL \
            --slow \
            --broadcast \
            --verify

Additional notes on Foundry Pipeline

If you'd like to use specific address for the deployment and verification of contracts on Virtual TestNets you can do so by following these steps:

  1. Add your private key to GitHub Secrets (through UI or CLI)
  2. Update your workflow to include wallet funding and deployment:
      - name: Fund Wallet
        run: |
          curl --location ${{ env.TENDERLY_ADMIN_RPC_URL }} \
          --header 'Content-Type: application/json' \
          --data '{
            "jsonrpc": "2.0",
            "method": "tenderly_setBalance",
            "params": ["${{ secrets.WALLET_ADDRESS }}", "0xDE0B6B3A7640000"],
            "id": "1234"
          }'

      - name: Deploy Contracts
        env:
          FOUNDRY_ETH_RPC_URL: ${{ env.TENDERLY_PUBLIC_RPC_URL }}
          FOUNDRY_VERIFIER_URL: ${{ env.TENDERLY_FOUNDRY_VERIFICATION_URL }}
          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
          TENDERLY_ACCESS_TOKEN: ${{ secrets.TENDERLY_ACCESS_KEY }}
        run: |
          forge script script/Deploy.s.sol \
            --private-key $PRIVATE_KEY \
            --rpc-url $FOUNDRY_ETH_RPC_URL \
            --verifier-url $FOUNDRY_VERIFIER_URL \
            --etherscan-api-key $TENDERLY_ACCESS_TOKEN \
            --slow \
            --broadcast \
            --verify

Advanced Configuration

Advanced configuration examples demonstrate how to extend the basic Virtual TestNet setup for more complex scenarios, such as multi-network testing and custom chain configurations.

Multi-Network Testing

Use matrix strategy to test your contracts across multiple networks in parallel. This is particularly useful for protocols that deploy across multiple chains and need to ensure consistent behavior.

jobs:
  test:
    strategy:
      matrix:
        network: ['1', '137', '42161']  # Ethereum, Polygon, Arbitrum
    steps:
      - uses: Tenderly/[email protected]
        with:
          network_id: ${{ matrix.network }}
          chain_id: ${{ format('7357{0}', matrix.network) }}

Debugging

Enable debug logs by setting:

env:
  DEBUG: '@tenderly/github-action'

Notes

  • Virtual TestNets are automatically cleaned up after the workflow completes
  • Use matrix builds for testing across multiple networks
  • Contract verification works automatically. Follow the guides for verification with Hardhat and Foundry.
  • Use unique chain IDs when possible (e.g. by prefixing with 7357) to avoid transaction replay attacks.
  • If you don't want to use Github UI to add required variables, you can do the following with utilizing Github CLI. Commands that enable you do it are:
TENDERLY_PROJECT_NAME=...
TENDERLY_ACCOUNT_NAME=...
TENDERLY_ACCESS_KEY=...
gh variable set TENDERLY_PROJECT_NAME --body ${TENDERLY_PROJECT_NAME}
gh variable set TENDERLY_ACCOUNT_NAME --body ${TENDERLY_ACCOUNT_NAME}
gh secret set TENDERLY_ACCESS_KEY --body ${TENDERLY_ACCESS_KEY}

License

Tenderly

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published