合約交互與 ABI

合約交互與 ABI

學習目標

掌握合約間調用方式、接口定義、ABI 數據結構、Web3.js 訪問合約的方法。


合約間調用基礎

  • EOA(外部賬號)發起調用,可能觸發合約間的調用鏈
  • 調用者必須持有被調用合約的地址

方式一:同文件內直接調用

當兩個合約在同一個文件中時,可以直接通過合約類型和地址進行調用:

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract Callee {
    uint256 public x;

    function setX(uint _x) public {
        x = _x;
    }
}

contract Caller {
    address calleeAddress;

    constructor(address _callee) {
        calleeAddress = _callee;
    }

    function setCalleeX(uint _x) public {
        Callee callee = Callee(calleeAddress);
        callee.setX(_x);
    }
}

方式二:跨文件 import 調用

當合約分布在不同文件中時,使用 import 引入:

// 文件: Callee.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract Callee {
    uint256 public x;

    function setX(uint _x) public {
        x = _x;
    }
}
// 文件: Caller.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;
import "contracts/Callee.sol";

contract Caller {
    address calleeAddress;

    constructor(address _callee) {
        calleeAddress = _callee;
    }

    function setCalleeX(uint _x) public {
        Callee callee = Callee(calleeAddress);
        callee.setX(_x);
    }
}

方式三:通過接口調用

接口(Interface)等價於 ABI,不依賴被調用合約的源碼,只需知道函數簽名即可調用。

定義接口

// 文件: ICallee.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

interface ICallee {
    function setX(uint _x) external;
}

實現接口(不強制)

// 文件: Callee.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;
import "contracts/ICallee.sol";

contract Callee is ICallee {
    uint256 public x;

    function setX(uint _x) public {
        x = _x;
    }
}

通過接口調用

// 文件: Caller.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;
import "contracts/ICallee.sol";

contract Caller {
    address calleeAddress;

    constructor(address _callee) {
        calleeAddress = _callee;
    }

    function setCalleeX(uint _x) public {
        ICallee callee = ICallee(calleeAddress);
        callee.setX(_x);
    }
}

實際案例:訪問 USDT 合約

只需知道合約地址和接口,就能與鏈上已部署的合約交互。

  • USDT 合約地址:0xdAC17F958D2ee523a2206206994597C13D831ec7
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

interface IERC20 {
    function name() external view returns(string memory);
    function symbol() external view returns(string memory);
    function decimals() external view returns(uint8);
}

通過接口 + 地址即可讀取 USDT 的名稱、符號和精度,無需獲取 USDT 的源碼。


ABI(Application Binary Interface)

ABI 是合約的二進制接口描述,包含以下特徵:

  • 只有函數簽名信息,沒有實現代碼
  • EOA 通過 ABI 調用合約,合約之間通過接口調用
  • 編譯合約時自動生成

ABI 示意圖

ABI JSON 示例

{
    "abi": [
        {
            "inputs": [
                {
                    "internalType": "uint256",
                    "name": "_x",
                    "type": "uint256"
                }
            ],
            "name": "setX",
            "outputs": [
                {
                    "internalType": "uint256",
                    "name": "",
                    "type": "uint256"
                }
            ],
            "stateMutability": "nonpayable",
            "type": "function"
        }
    ]
}

Web3.js 合約訪問

Web3.js 是瀏覽器端調用合約的 JavaScript 庫,支持兩種引入方式:

  • 直接引用 <script> 標籤
  • Node.js 模塊(npm install web3

使用步驟

  1. 導入 Web3.js
  2. 調起 MetaMask 登錄,獲取用戶賬戶地址
  3. 用 ABI + 合約地址生成 contract 對象
  4. 調用合約方法
  5. 讀操作(view/pure):.methods.funcName().call()
  6. 寫操作(修改狀態):.methods.funcName().send({ from: account })

代碼示例

// 1. 導入 Web3(瀏覽器環境,MetaMask 注入 window.ethereum)
const web3 = new Web3(window.ethereum);

// 2. 請求 MetaMask 授權登錄
const accounts = await window.ethereum.request({
    method: "eth_requestAccounts"
});
const account = accounts[0];

// 3. 用 ABI + 合約地址創建 contract 對象
const abi = [ /* 合約 ABI JSON */ ];
const contractAddress = "0x1234...abcd";
const contract = new web3.eth.Contract(abi, contractAddress);

// 4a. 讀操作(view 函數,不消耗 gas)
const value = await contract.methods.getX().call();
console.log("當前值:", value);

// 4b. 寫操作(修改狀態,消耗 gas,需要簽名)
await contract.methods.setX(42).send({ from: account });

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/7492

(0)
Walker的頭像Walker
上一篇 5天前
下一篇 2025年3月27日 15:01

相關推薦

  • 引用類型詳解:數組、結構體、映射、字符串

    引用類型詳解:數組、結構體、映射、字符串 學習目標 掌握 Solidity 中四種引用類型(數組、結構體、映射、字符串/變長字節數組)的定義和使用方法。 前置知識 已學習值類型(整型、布爾、地址、定長字節數組等)。 數組(Array) storage 中的數組 Solidity 中數組分為兩種: 靜態數組 T[K]:長度固定,編譯時確定 動態數組 T[]:長…

  • Solidity 值類型詳解

    Solidity 值類型詳解 學習目標 掌握 Solidity 的整型、布爾、地址、定長字節數組、枚舉等值類型 理解 EVM 256 位機器架構對類型設計的影響 掌握類型轉換規則(隱式 vs 顯式) 瞭解溢出問題的歷史與解決方案 理解 Solidity 中所有類型的默認值機制 一、整型(int / uint) 1.1 基本概念 Solidity 提供有符號整…

  • Gas機制與轉賬設計

    Gas機制與轉賬設計 學習目標 理解區塊鏈的經濟模型與激勵機制 掌握 Gas、Gas Price、Gas Fee 的概念與關係 理解 Ether 單位與轉換 掌握合約轉賬設計(receive / fallback / payable) 區塊鏈的經濟系統 為甚麼需要經濟模型? 計算與存儲資源是稀缺的:每個節點都要執行和存儲所有交易 共識和 trustless …

    20小時前
    000
  • Solidity 入門與開發環境

    Solidity 入門與開發環境 學習目標 理解智能合約的本質與核心特性 掌握合約在以太坊上的運行原理(Transaction + EVM) 認識 Solidity 語言特點與開發工具鏈 編寫並部署第一個智能合約 前置知識 瞭解區塊鏈基本概念(區塊、交易、共識) 瞭解以太坊賬戶模型(EOA 與合約賬戶) 基本編程經驗(任意語言均可) 一、智能合約的根本性質 …

    1天前
    900
  • 存儲位置與拷貝機制:storage、memory、calldata

    存儲位置與拷貝機制:storage、memory、calldata 學習目標 理解 EVM 中三種數據存儲位置的特點,以及引用類型在不同存儲位置之間賦值時的拷貝規則。 前置知識 已學習值類型和引用類型(數組、結構體、映射、字符串)。 三種存儲位置 storage —— 持久化存儲 類似數據庫,數據永久保存在區塊鏈上 成員變量(狀態變量)默認存儲在 stora…

簡體中文 繁體中文 English