在以太坊生態(tài)系統(tǒng)中,智能合約是自動執(zhí)行、控制或記錄法律相關(guān)的重要條款或行動的計算機協(xié)議,而“發(fā)送交易”是以太坊網(wǎng)絡(luò)中進行狀態(tài)改變的基本操作,當我們談?wù)摗耙蕴话l(fā)送交易合約”時,通常指的是兩種情境:一是如何通過一個智能合約來主動發(fā)起一筆交易(即合約作為交易發(fā)送方);二是如何向一個智能合約發(fā)送交易以調(diào)用其函數(shù)(即外部用戶或其他合約與合約交互),本文將重點探討前者,即合約如何主動發(fā)送交易,并解釋其背后的機制、步驟和注意事項。

為什么需要合約發(fā)送交易

智能合約不僅僅是被動接收調(diào)用的代碼庫,許多復(fù)雜的業(yè)務(wù)邏輯需要合約在特定條件下主動與其他合約甚至普通賬戶進行交互。

  1. 代幣轉(zhuǎn)賬:一個去中心化交易所(DEX)合約,在用戶完成流動性提供后,需要自動將LP代幣發(fā)送給用戶。
  2. 理賠處理:一個保險合約,在達到理賠條件時,主動將賠償款發(fā)送給投保人。
  3. 治理投票:一個DAO合約,在提案通過后,自動執(zhí)行資金劃撥或合約升級操作。
  4. 跨鏈交互:一個跨鏈橋合約,在驗證到鏈上交易后,主動在目標鏈上鑄造或轉(zhuǎn)移資產(chǎn)。

在這些場景中,合約作為“主動方”發(fā)送交易是核心功能。

合約發(fā)送交易的核心機制:.call()、.delegatecall()、.staticcall().transfer()/.send()/.sendValue() (Solidity >=0.8.0)

在Solidity中,合約要發(fā)送交易或調(diào)用其他合約,通常使用以下方法:

  1. 低級調(diào)用 (Low-Level Calls)

    • .call():這是最常用、最靈活的方法,它可以發(fā)送以太坊(ETH)并調(diào)用目標合約的指定函數(shù),它會返回一個布爾值表示調(diào)用是否成功,如果調(diào)用失?。ㄈ缒繕撕霞s不存在、函數(shù)不存在、gas不足、 revert等)會拋出錯誤(在Solidity 0.8.x之前需要手動檢查返回值,0.8.x之后默認拋出錯誤,但仍可使用try/catch)。
      // 示例:合約A調(diào)用合約B的receiveFunction,并發(fā)送1 ETH
      (bool success, ) = payable(address(contractB)).call{value: 1 ether}("");
      require(success, "Call to contractB failed");

      或者調(diào)用特定函數(shù):

      (bool success, ) = contractB.functionName{value: 1 ether, gas: 100000}(arg1, arg2);
      require(success, "Call to contractB.functionName failed");
    • .delegatecall():與.call()不同,.delegatecall()在調(diào)用目標合約的代碼時,使用的是當前合約的存儲和上下文,這主要用于庫(Libraries)的調(diào)用,或者在升級代理模式(Proxy Pattern)中實現(xiàn)邏輯合約的升級。
    • .staticcall():用于只讀調(diào)用,它保證不會修改合約的狀態(tài)(即不能發(fā)送ETH或調(diào)用會修改狀態(tài)的函數(shù)),如果目標函數(shù)嘗試修改狀態(tài),.staticcall()會失敗。
  2. 發(fā)送ETH的方法

    隨機配圖