合约交互与 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
上一篇 2026年5月12日 13:53
下一篇 2026年5月12日 13:08

相关推荐

  • Web3 概述与愿景

    Web3 概述与愿景 学习目标 理解 Web1、Web2、Web3 的演进历程与核心区别 掌握 Web3 的核心理念:去中心化、数据确权、用户主权 了解 Web3 带来的创新机会与全新商业模式 熟悉 Web3 开发者的学习路线图 前置知识 基本的互联网使用经验 对软件开发有初步了解(非必须,但有助于理解技术部分) 一、Web1 → Web2 → Web3 的…

    Web3与WASM 2026年3月10日
    11700
  • Delegatecall 与代理模式

    Delegatecall 与代理模式 学习目标 理解 delegatecall 的工作原理 掌握 Storage Layout(存储布局)规则 掌握代理模式与合约升级 了解非结构化存储(Unstructured Storage) delegatecall 原理 什么是 delegatecall 语法:address.delegatecall(bytes ca…

    2026年3月10日
    12600
  • 区块链核心技术

    区块链核心技术 学习目标 理解区块链底层核心技术:哈希函数、默克尔树、数字签名、加密技术 掌握主流共识机制的原理与分类 了解区块的运行原理与整体架构 认识联盟链的特点与应用场景 前置知识 基本的计算机科学概念(数据结构、算法) 对密码学有初步认知(非必须) 已阅读 01-Web3 概述与愿景 一、哈希函数 1.1 什么是哈希函数 哈希函数(Hash Func…

    2026年3月10日
    18700
  • Solidity 值类型详解

    Solidity 值类型详解 学习目标 掌握 Solidity 的整型、布尔、地址、定长字节数组、枚举等值类型 理解 EVM 256 位机器架构对类型设计的影响 掌握类型转换规则(隐式 vs 显式) 了解溢出问题的历史与解决方案 理解 Solidity 中所有类型的默认值机制 一、整型(int / uint) 1.1 基本概念 Solidity 提供有符号整…

    Web3与WASM 2026年3月10日
    15700
  • 函数定义与访问控制

    函数定义与访问控制 学习目标 掌握 Solidity 函数定义、可见性修饰符、交易属性、modifier 和构造函数。 函数定义 一般形式 function fname([参数]) [可见性][交易属性][modifier...] returns(返回值) { ... } 函数签名:fname([参数]) —— 唯一标识一个函数 返回值:returns(返回…

    Web3与WASM 2026年3月10日
    10000
简体中文 繁体中文 English