尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WTF Solidity 极简入门:抽象合约(abstract)与接口(interface)——以 IERC721 为例的深度实战解析

WTF Solidity 极简入门:抽象合约(abstract)与接口(interface)——以 IERC721 为例的深度实战解析 WTF Solidity 极简入门抽象合约abstract与接口interface——以 IERC721 为例的深度实战解析【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity本指南是 WTF-Solidity 教程第 14 讲围绕 Solidity 中两个核心的代码复用与标准化工具——抽象合约abstract与接口interface展开。文章以ERC721标准接口IERC721为主线结合 WTF-Solidity 仓库中 14_Interface 与 34_ERC721 的源码实现讲解抽象合约的声明规则、接口的五大约束、IERC721的 3 个事件与 9 个函数并演示如何仅凭接口与合约地址与主网上的 Bored Ape Yacht ClubBAYCNFT 合约进行交互。读完本文你将掌握用abstract编写模板合约、用interface定义链上标准契约并能在自己的 DApp 中安全地调用任意已知标准的合约。抽象合约为未实现的功能预留模板如果某个合约中至少有一个函数没有实现——即函数缺少函数体{}中的内容——那么这个合约必须被标记为abstract否则编译会直接报错。同时未实现的函数必须加上virtual关键字以便子合约可以通过override重写它。以本仓库 10_InsertionSort 中的插入排序合约为例如果暂时还没想好具体的排序实现可以先把合约标为abstract把函数签名写好留待后续或让其他开发者补全abstract contract InsertionSort { function insertionSort(uint[] memory a) public pure virtual returns (uint[] memory); }对应源码见 14_Interface/Interface.sol其中insertionSort以分号结尾、没有函数体正是抽象合约中未实现函数的典型写法。一个完整的抽象合约继承示例仓库中的 AbstractDemo.sol 给出了抽象合约从声明到被实现的完整链路// SPDX-License-Identifier: MIT pragma solidity ^0.8.34; abstract contract Base { string public name Base; function getAlias() public pure virtual returns(string memory); } contract BaseImpl is Base { function getAlias() public pure override returns(string memory) { return BaseImpl; } }关键点解读Base中getAlias()只有声明没有函数体因此Base必须是abstract且getAlias被标记为virtualBaseImpl继承Base并实现了getAlias()返回BaseImpl同时用override明确声明这是对父合约抽象函数的覆写注意name状态变量在抽象合约中可以存在——这是抽象合约与接口的一个重要区别接口严禁状态变量。接口智能合约的骨架与标准契约接口interface类似于抽象合约但它完全不实现任何功能只描述这个合约能做什么、怎么触发。Solidity 对接口有五条硬性规则不能包含状态变量不能包含构造函数不能继承除接口以外的其他合约但可以继承别的接口所有函数都必须是external类型且不能有函数体继承接口的非抽象合约必须实现接口中定义的所有功能事件除外。尽管接口不实现任何逻辑它却是智能合约体系中最重要的类型之一。接口就是智能合约的骨架定义了合约的功能以及如何触发它们只要一个智能合约声明实现了某种接口如ERC20、ERC721其他 DApp 和智能合约就知道如何与它交互。这是因为接口提供了两条关键信息合约中每个函数的函数签名函数名(每个参数类型)以及对应的bytes4选择器通过对函数签名做哈希运算后取前 4 字节获得该接口的接口 ID更多细节见 EIP-165 规范。此外接口与合约的 ABIApplication Binary Interface等价可以相互转换编译接口即可得到合约的 ABI反过来利用 abi-to-sol 工具也可以把json格式的 ABI 文件转换成sol格式的接口文件。IERC721NFT 世界的标准骨架本仓库 34_ERC721/IERC721.sol 中定义了完整的IERC721接口它继承了IERC165见 34_ERC721/IERC165.sol声明了supportsInterface(bytes4 interfaceId) external view returns (bool)并声明了3 个事件和 9 个函数。所有遵循ERC721标准的 NFT 都必须实现这些函数。对比普通合约可以看到接口中每个函数都以;代替函数体{}结尾interface IERC721 is IERC165 { event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function balanceOf(address owner) external view returns (uint256 balance); function ownerOf(uint256 tokenId) external view returns (address owner); function safeTransferFrom(address from, address to, uint256 tokenId) external; function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; function getApproved(uint256 tokenId) external view returns (address operator); function setApprovalForAll(address operator, bool _approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; }在 14_Interface/Interface.sol 中保留了与之完全一致的接口声明可直接编译验证。IERC721 的 3 个事件Transfer在转账时被释放记录代币的发出地址from、接收地址to和tokenId。该事件在ERC20中同样存在。Approval在授权时被释放记录授权地址owner、被授权地址approved和tokenId。ERC20中也有同名事件。ApprovalForAll在批量授权时被释放记录批量授权的发出地址owner、被授权地址operator以及授权与否的布尔值approved。IERC721 的 9 个函数balanceOf返回某地址owner的 NFT 持有量balance。ownerOf返回某tokenId的主人owner。transferFrom普通转账参数为转出地址from、接收地址to和tokenId。safeTransferFrom安全转账若接收方是合约地址会要求其实现ERC721Receiver接口参数为转出地址from、接收地址to和tokenId。approve授权另一个地址使用你的 NFT参数为被授权地址to和tokenId。getApproved查询某个tokenId被批准给了哪个地址。setApprovalForAll将自己持有的该系列 NFT 批量授权给某个地址operator。isApprovedForAll查询某地址owner的 NFT 是否已批量授权给另一个operator地址。safeTransferFrom重载安全转账的重载函数在原有参数基础上增加了一个data参数注意该重载在 34_ERC721/IERC721.sol 中是显式声明的独立函数签名。接口如何在源码层面落地以 ERC721 实现为例接口定义的是约定而真正的逻辑在实现合约中。仓库 34_ERC721/ERC721.sol 中的ERC721合约通过contract ERC721 is IERC721, IERC721Metadata继承并逐一override实现了这些函数。例如supportsInterface通过type(IERC721).interfaceId上报自己支持的接口见 ERC721.solbalanceOf、ownerOf则通过内部的_balances、_owners映射返回真实数据见 ERC721.sol。这一实现模式印证了接口规则的第五条继承接口的合约必须实现接口定义的全部功能而接口本身只负责定义标准、暴露入口。实战仅凭接口地址交互 BAYC 合约当我们知道某个合约实现了IERC721接口时完全不需要了解它的源代码实现只要知道合约地址就能通过接口安全地与之交互。无聊猿BAYC是ERC721类型的 NFT 代币实现了IERC721接口的全部功能。我们不知道它的源码也能用balanceOf()查询某地址的BAYC余额用safeTransferFrom()转账BAYC。仓库 14_Interface/Interface.sol 中的interactBAYC合约演示了完整的交互写法contract interactBAYC { // 利用 BAYC 地址创建接口合约变量ETH 主网 IERC721 BAYC IERC721(0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D); // 通过接口调用 BAYC 的 balanceOf() 查询持仓量 function balanceOfBAYC(address owner) external view returns (uint256 balance){ return BAYC.balanceOf(owner); } // 通过接口调用 BAYC 的 safeTransferFrom() 安全转账 function safeTransferFromBAYC(address from, address to, uint256 tokenId) external{ BAYC.safeTransferFrom(from, to, tokenId); } }这段代码的两个核心技巧接口类型变量IERC721 BAYC IERC721(0xBC4C...6f13D)相当于把一个已知的链上地址声明为一个IERC721类型的变量此后BAYC的每一次调用都会以该接口的函数签名作为 calldata 发送到该地址零实现成本交互调用BAYC.balanceOf(owner)时编译器依据接口声明生成对应的函数选择器底层通过call转发给目标合约从而在不依赖目标源码的情况下完成链上调用。与之配套的 InterfaceDemo.sol 还给出了一个更简单的接口实现示例——定义Base接口含getFirstName()、getLastName()两个纯函数再由BaseImpl合约override实现并返回Amazing与Ang可直接在 Remix 中体验定义接口 → 实现接口的完整流程。在 Remix 上验证以下两张截图来自本讲在 Remix IDE 中的实际部署与调用验证抽象合约示例14-1.png编译 AbstractDemo.sol在 Remix 的DEPLOY RUN TRANSACTIONS面板中选择BaseImpl合约并部署。部署成功后调用getAlias()得到BaseImpl、读取name得到Base直观验证了抽象合约Base中虚拟函数被子合约BaseImpl成功重写。接口示例14-2.png编译 InterfaceDemo.sol部署BaseImpl合约后调用getFirstName()与getLastName()分别返回Amazing与Ang验证了接口中声明的每个函数都必须被继承合约完整实现这一约束。总结本讲围绕 WTF-Solidity 第 14 讲的葡萄牙语教程主体系统讲解了 Solidity 中的两个代码组织利器抽象合约abstract允许合约包含未实现的virtual函数为后续实现预留模板同时可以保留状态变量与已实现函数接口interface只声明不实现受五条规则约束无状态变量、无构造函数、只能继承接口、函数全为external且无函数体、继承者须实现全部功能是链上标准的骨架。两者都能编写模板并减少代码冗余。我们还深入拆解了ERC721的接口合约IERC7213 个事件 9 个函数源码见 34_ERC721/IERC721.sol并演示了如何仅凭接口类型与主网地址与无聊猿BAYC合约完成查询与转账交互。掌握接口思维是理解 OpenZeppelin 标准合约、开发可组合 DApp 以及阅读一切ERC系列规范的基础。【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表