一、總覽:6 步閉環

  1. 用户點擊按鈕
  2. 前端組裝交易數據(calldata)
  3. 錢包簽名 → 生成 SignedTx
  4. 節點廣播 → 網絡挖礦打包
  5. 鏈上執行合約邏輯 → 更新狀態
  6. 前端監聽事件 / 讀鏈回顯 → UI 刷新

二、各層角色與工具

層級

作用

常用庫 / 對象

錢包

私鑰保管 + 簽名

MetaMask、WalletConnect、Coinbase Wallet

前端運行時

提供 Provider / Signer

ethers.js v6、web3.js、viem

RPC 節點

廣播 & 查詢

Infura、Alchemy、QuickNode、本地 Hardhat

鏈上

執行字節碼

EVM

事件日誌

通知前端

ethers.on(event, handler)


三、最小可運行範例(React + ethers v6)

① 連接錢包 → 拿到 signer

const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []); // 彈出 MetaMask
const signer = await provider.getSigner();      // 得到可簽名對象

② 創建合約實例

const pool = new ethers.Contract(
  '0xEDb4C07B6AfFb61C2A2fa22cBb30552b4F7748f4', // 代理地址
  STAKE_ABI,                                     // 邏輯 ABI
  signer                                         // 必須帶簽名能力
);

③ 寫操作:質押 0.1 ETH

const tx = await pool.depositEth(0, { value: ethers.parseEther('0.1') });
console.log('txHash', tx.hash);
await tx.wait();           // 等待鏈上確認
console.log('區塊號', tx.blockNumber);

④ 讀操作:查詢已質押

const [amountWei] = await pool.users(0, signer.address);
console.log('已質押', ethers.formatEther(amountWei), 'ETH');

⑤ 監聽事件(可選)

pool.on('Staked', (user, poolId, amount, stakedAt, unlockTime) => {
  if (user === signer.address) {
    console.log('我剛質押了', ethers.formatEther(amount), 'ETH');
  }
});

四、交易生命週期拆解

  1. 構造調用數據
    depositEth(0) → ABI 編碼 → calldata = 0x441a3e70...
  2. 錢包簽名
    MetaMask 把 calldata + gasPrice / gasLimit / nonce / chainId 打包 → 私鑰簽名 → 得到 rawSignedTx
  3. 廣播與挖礦
    前端通過 eth_sendRawTransaction 把簽名交易發給 RPC → 節點 mempool → 礦工打包 → 出塊
  4. EVM 執行
    節點執行合約字節碼:更新 storage(_amountTotal、unclaimedRewards…)、 emit 事件日誌
  5. 回執與事件
    交易回執(receipt)包含:status / gasUsed / logs → 前端 await tx.wait() 拿到回執 → 解析日誌 → UI 刷新

五、常見坑速查

現象

原因

修復

contract runner does not support sending transactions

給了 provider 沒給 signer

new Contract(addr, abi, signer)

revert: Not enough unlocked stakes

鎖倉期未滿

unlockTime 或只解已解鎖部分

insufficient funds

錢包 ETH 不夠付 gas + value

減少金額或領測試幣

gas estimation failed

參數傳錯/合約內部 revert

call 靜態模擬,看 revert 信息


六、進階交互模式

  1. 離線簽名 → 用 Wallet #signTransaction,適合後端批處理
  2. EIP-712 結構化簽名 → 減少誤導,提高可讀性
  3. ** multicall ** → 把多筆只讀調用打包,一次 RPC 返回
  4. 事件掃描 → 用 queryFilter 拉歷史日誌,做分頁/圖表
  5. Gas 策略 → EIP-1559 動態 maxFeePerGas,或手動加速取消

七、一句話總結

Web3 前端與合約交互 = 用 ethers/js 把用户操作編碼成 calldata → 讓錢包簽名 → 通過 RPC 廣播 → 鏈上執行後讀回 events / storage → 刷新 UI。