假如一个智能合约中至少一个函数缺省实现时,即某个函数缺少{}中的内容,这个智能合约就当做抽象智能合约。
当我们有一个函数没想好怎么写时,必须将该合约标为abstract
,不然编译会报错;另外,未实现的函数需要加virtual
,以便子合约重写。抽象智能合约是将智能合约的定义与实现部分分离,从而提供更好的可扩展性和易读性。
- abstract contract InsertionSort{
- function insertionSort(uint[] memory a) public pure virtual returns(uint[] memory);
- }
需要注意的是,缺省实现的函数虽然跟function类型的变量在语法上看起来很像,但两者完全不同,缺省实现的函数如下:
function foo(address) external returns (adderss);
function类型的变量在声明时如下:
function(address) exteranl returns (address) foo;
接口类似于抽象智能合约,但是不实现任何功能:
接口是智能合约的骨架,定义了合约的功能以及如何触发它们:如果智能合约实现了某种接口(比如ERC20
或ERC721
),其他Dapps和智能合约就知道如何与它交互。因为接口提供了两个重要的信息:
bytes4
选择器,以及基于它们的函数签名函数名(每个参数类型)
。另外,接口与合约ABI
(Application Binary Interface)等价,可以相互转换:编译接口可以得到合约的ABI
,利用abi-to-sol工具也可以将ABI json
文件转换为接口sol
文件。
ERC721
接口合约IERC721
为例,它定义了3个event
和9个function
,所有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;
- }
我们知道一个合约实现了IERC721
接口,我们不需要知道它具体代码实现,就可以与它交互。