基于Solidity构建CTF竞赛网站的完整指南

[Web 3.0] 如何建立CTF比賽網站(Solidity)

很榮幸有機會加入DefiHackLabs台灣區的Operations並完成DEFIHACKLABS ETHEREUM AND WEB3 SECURITY BOOTCAMP。可能大家會好奇最後一天比賽網站是怎麼架設的,這邊就說明一下(開始吧):love-you_gesture:

靈感其實是來自BuidlGuidl CTF - Devcon SEA 2024的專案,連結如下:
https://github.com/BuidlGuidl/ctf.buidlguidl.com/tree/devcon-2024

BuidlGuidl提供許多腳手架可以快速架設並學習其中技術,推薦大家去學習。

1. 環境準備

  • Node (>= v18.18)
  • Yarn (v1 or v2+)
  • Git

2. 克隆代碼庫

將檔案git clone到自己的電腦中:

git clone git@github.com:BuidlGuidl/ctf.buidlguidl.com.git

3. 項目架構解說

ctf-devcon/
└── packages/
    ├── hardhat/ // hardhat工具(合約存放處)
    ├── nextjs/  // 網頁程序
    ├── scripts/ // 執行script的目錄(未使用)
    └── ponder/  // Ponder是區塊鏈應用後端的開源框架

使用一張圖來理解執行流程:

如上圖所示,使用Alchemy API取得訊息和Ponder來獲取自訂的區塊鏈結構資料,另外將網站部署到Vercel上。

4. 使用Hardhat部署到Holesky測試鏈

(最好具備hardhat的基礎概念)

4.1 配置hardhat.config.ts

設定相關訊息:

  • providerApiKey
  • deployerPrivatKey
  • etherscanApiKey(非必要)
  • 新增holesky networks
const providerApiKey = process.env.ALCHEMY_API_KEY // alchemy api key
const deployerPrivateKey = process.env.DEPLOYER_PRIVATE_KEY // 部署錢包的私鑰
const etherscanApiKey = process.env.ETHERSCAN_API_KEY 

networks: {
    holesky: {
      url: `https://eth-holesky.g.alchemy.com/v2/${providerApiKey}`,
      accounts: [deployerPrivateKey],
      verify: {
        etherscan: {
          apiUrl: "https://api-holesky.etherscan.io",
          apiKey: `${etherscanApiKey}`,
        },
      },
    }
  },

process.env是從.env環境變數取得,這些訊息通常不應暴露。

4.2 獲取ALCHEMY_API_KEY

  1. 進入 https://auth.alchemy.com/ 登入
  2. 進入後 apps/create new app
  3. 選擇chains, Activate services
    紅框處就是ALCHEMY_API_KEY,Network URL也可以在這裡取得

4.3 執行script部署

檔案分布如下:

ctf-devcon/
└── packages/
    ├── hardhat/          
    ├── contracts/ // 目標合約
    ├── deploy/ // 部署的script
        └── 00_deploy_ctf_contracts.ts

對於00_deploy_ctf_contracts.ts的部分修改,如需新合約可自行添加:

// :: Challenge 2 ::
const challenge2Deployment = await deploy("Challenge2", {
    from: deployer,
    args: [await nftFlags.getAddress()],
    log: true,
    autoMine: true,
});
console.log(":triangular_flag: Challenge #2 deployed");
if (!challenge2Deployment.transactionHash) {
    throw new Error("No transaction hash found for Challenge2 deployment");
}
const challenge2deploymentTx = await hre.ethers.provider.getTransaction(challenge2Deployment.transactionHash);
// 新增等待區塊5才繼續部署(如需verify則必須執行此步驟)
const challenge2receipt = await challenge2deploymentTx.wait(5);

執行以下命令,將會把abi等檔案同步到nextjs/deployedContracts.js:

yarn deploy --tags CTF --network holesky

探究yarn deploy同步原理,可研究hardhat.config.ts中的generateTsAbis:

// deploy設定之後的動作
task("deploy").setAction(async (args, hre, runSuper) => {
    // 執行原始deploy任務
    await runSuper(args);
    // 強制執行generateTsAbis腳本
    await generateTsAbis(hre);
});

5. 部署網站PONDER_URL

Ponder是區塊鏈應用後端的開源框架,可快速建立和部署API,為任何EVM區塊鏈上的智能合約提供自訂資料。我們使用https://railway.com/來部署(註冊部分省略)。

說明上圖:

  1. 取得新專案
  2. 設定環境變數
  3. Generate Domain(之後配置到next.js環境變數NEXT_PUBLIC_PONDER_URL)
  4. build完成後執行Deploy command -> yarn ponder:start

5.1 PONDER說明

查看ponder/src/Challenge1.ts和NFTFlags.ts,取其中一個檔案說明:

// 可看到利用此方式可自訂鏈上訊息,讓前端透過gql調用
// 參考packages/nextjs/app/leaderboard/page.tsx第38行
import { ponder } from "@/generated";

ponder.on("Challenge1:TeamInit", async ({ event, context }) => {
    const { Team } = context.db;
    await Team.upsert({
        id: event.args.team,
        create: {
            points: 0,
            sortOrder: 0n,
            name: event.args.name,
            size: event.args.teamSize,
            updated: Number(event.block.timestamp),
        },
        update: {
            name: event.args.name,
            size: event.args.teamSize,
            updated: Number(event.block.timestamp),
        },
    });
});

6. 設定基本資料

網站目錄在next.js,主要設定scaffold.config:

const scaffoldConfig = {
    // DApp運行的網絡
    targetNetworks: [chains.holesky], // 目標網絡
    // indexer的startBlock
    startBlock: 3167275, // 開始的block(必須設定否則無資料)
    // 前端輪詢RPC服務器獲取新數據的間隔
    // 如僅針對本地網絡則無效(默認4000)
    pollingInterval: 10000, // 獲取新資料的間隔時間
    // 這是我們的Alchemy默認API密鑰
    // 您可以在https://dashboard.alchemyapi.io獲取自己的密鑰
    // 建議存儲在環境變量中:
    // .env.local用於本地測試,Vercel/system env config用於實時應用
    alchemyApiKey: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY,
    // 這是我們的WalletConnect默認項目ID
    // 您可以在https://cloud.walletconnect.com獲取自己的ID
    // 建議存儲在環境變量中:
    // .env.local用於本地測試,Vercel/system env config用於實時應用
    walletConnectProjectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID,
    // 僅在hardhat網絡上顯示Burner Wallet
    onlyLocalBurnerWallet: true,
} as const satisfies ScaffoldConfig;

6-1. 使用Vercel部署網站

  1. Add New
  2. import project
  3. select framework
  4. setting env

部署完畢後會有這個畫面:

恭喜你部署成功 :star-struck:

可以參考:https://ctf-devcon.vercel.app/

分享當天比賽的畫面 :grinning_face_with_smiling_eyes:

簡單記錄一下希望對大家有幫助,我們下次見啦 :waving_hand:
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码

posted @ 2025-07-26 15:06  qife  阅读(12)  评论(0)    收藏  举报