solidity高阶 -- 调用接口合约

        在区块链开发中,Solidity 是一种广泛使用的智能合约编程语言,而接口合约(Interface)是 Solidity 中一个非常重要的概念。它为智能合约之间的交互提供了一种标准化的方式,使得合约之间的调用更加灵活、安全且易于管理。本文将深入探讨 Solidity 中接口合约的概念、作用以及具体的实现示例。

         注意:使用继承时请确保代码的正确性,以防丢失个人财产,在这里友情提示您,不要复制来源不明的solidity代码并进行部署。本文为自己梳理总结,如有不足还请指出,感谢包容。 

        学习更多solidity知识请访问 Github -- solidity基础 ,更多实例在 Smart contract

 

二、接口合约的作用

(一)抽象化合约交互

        接口合约将合约的调用逻辑与实现细节分离,使得合约之间的交互更加抽象化。开发者只需要关注接口的定义,而无需关心目标合约的具体实现。这种抽象化的方式使得合约之间的耦合度降低,提高了代码的可维护性和可扩展性。

        例如,假设我们有一个 Counter 合约,它实现了 ICounter 接口。其他合约可以通过 ICounter 接口调用 Counter 合约的函数,而无需知道 Counter 合约的具体实现细节。

(二)提高代码复用性

        接口合约可以被多个合约实现,从而实现代码的复用。多个合约可以共享同一个接口定义,而每个合约可以根据自己的需求实现接口中的函数。这种方式避免了重复编写类似的函数逻辑,提高了开发效率。

(三)增强安全性

        接口合约提供了一种明确的调用规范,使得合约之间的交互更加安全。通过接口合约,调用方可以明确知道目标合约提供的函数签名和返回值类型,从而避免因调用错误而导致的安全问题。同时,接口合约还可以限制调用方对目标合约的访问权限,进一步增强合约的安全性。

 

三、接口合约的实现示例

为了更好地理解接口合约的作用,我们通过一个具体的示例来展示如何使用接口合约。

(一)定义接口合约

首先,我们定义一个接口合约 ICounter,它包含两个函数:count()inc()

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

interface ICounter {
    function count() external view returns (uint);
    function inc() external;
}

(二)实现接口合约

        接下来,我们定义一个 Counter 合约,它实现了 ICounter 接口。Counter 合约包含一个状态变量 count,以及两个函数:inc()dec()。其中,inc() 函数用于增加 count 的值,dec() 函数用于减少 count 的值。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

contract Counter {
    uint public count;

    function inc() external {
        count += 1;
    }

    function dec() external {
        count -= 1;
    }
}

(三)调用接口合约

最后,我们定义一个 CallInterface 合约,它通过 ICounter 接口调用 Counter 合约的函数。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

contract CallInterface {
    uint public count;

    function examples(address _counter) external {
        ICounter(_counter).inc();
        count = ICounter(_counter).count();
    }
}

        在 CallInterface 合约中,examples() 函数接收一个合约地址 _counter,并通过 ICounter(_counter) 将该地址转换为 ICounter 类型。然后,调用 ICounter 接口的 inc() 函数来增加 Counter 合约的 count 值,并通过 count() 函数获取当前的 count 值,将其存储在 CallInterface 合约的 count 状态变量中。

 

四、接口合约与抽象合约的区别

        在 Solidity 中,除了接口合约,还有一种类似的合约类型——抽象合约。抽象合约和接口合约有一些相似之处,但也有明显的区别。

(一)定义方式

  • 接口合约:以关键字 interface 开始,函数声明必须是 external 类型,不能包含状态变量。

  • 抽象合约:以关键字 contract 开始,可以包含 externalinternal 函数,也可以包含状态变量。

(二)实现方式

  • 接口合约:接口合约中的函数必须由实现合约提供具体实现,且不能包含任何逻辑。

  • 抽象合约:抽象合约中的函数可以是抽象函数(没有实现),也可以是具体实现的函数。实现合约可以选择实现抽象函数,也可以直接继承抽象合约中的具体实现。

(三)使用场景

  • 接口合约:主要用于定义合约之间的交互规范,使得合约之间的调用更加标准化和抽象化。

  • 抽象合约:主要用于提供一组通用的函数和状态变量,供其他合约继承和扩展。抽象合约可以包含部分实现逻辑,使得继承合约可以复用这些逻辑。

五、关键注意事项

  1. 严格签名匹配:包括参数类型、返回值、可见性(external必须严格一致)

  2. 版本兼容:需使用相同Solidity编译器版本

  3. 限制特性

    • 不能包含构造函数

    • 不能定义状态变量

    • 不能继承其他合约

  4. 返回处理:view函数通过返回值获取数据,非view函数通过事件监听状态变化

 

六、典型应用场景

  1. 代币交互:ERC20标准接口

  2. 预言机调用:数据请求标准化

  3. 可升级合约:通过接口指向不同实现

  4. 合约检测:通过接口判断合约功能支持性

 

七、开发实践建议

  1. 接口命名使用"I"前缀(如ICounter

  2. 为每个功能模块定义独立接口

  3. 使用TypeChain等工具自动生成TypeScript类型定义

  4. 结合require语句进行接口支持检测:

    require(
        Counter(_counter).supportsInterface(type(ICounter).interfaceId),
        "Unsupported interface"
    );

八、本文代码总结

接口合约ICounter

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

contract Counter {
    uint public count;

    function inc() external {
        count += 1;
    }
    function dec() external {
        count -= 1;
    }
    }
//调用接口合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

interface ICounter {
    function count() external view returns (uint);
    function inc() external;
}
//interface开头,名字大写,完成了接口调用的方法
//调用了两个合约的函数

contract CallInterface {
    uint public count;
    
    function examples(address _counter) external {
        ICounter(_counter).inc();
        count = ICounter(_counter).count();
    }
}
//调用inc这个方法
// count = ICounter(_counter).count();

 

结语

        接口合约如同智能合约世界的通信协议,通过定义清晰的交互边界,极大地提升了合约系统的可维护性和扩展性。当您下次需要实现跨合约调用时,不妨先设计好接口规范——这如同为合约间的对话制定语法规则,将使您的DApp架构更加优雅稳健。

        通过文中的Counter示例实践可以发现,接口合约将功能声明与具体实现分离,既保证了核心逻辑的安全性,又为后续功能扩展保留了充足的灵活性。这正是区块链智能合约开发中"合约优先"设计理念的生动体现。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964761.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【B站保姆级视频教程:Jetson配置YOLOv11环境(七)Ultralytics YOLOv11配置】

Jetson配置YOLOv11环境(7)Ultralytics YOLOv11环境配置 文章目录 1. 下载YOLOv11 github项目2. 安装ultralytics包3. 验证ultralytics安装3.1 下载yolo11n.pt权重文件3.2 推理 1. 下载YOLOv11 github项目 创建一个目录,用于存放YOLOv11的项目…

代码讲解系列-CV(二)——卷积神经网络

文章目录 一、系列大纲二、卷积神经网络(图像分类为例)2.1 pytorch简介训练框架张量自动微分动态计算图更深入学习 2.2 数据输入和增强Dataset—— torch.utils.data.DatasetDataLoader——torch.utils.data.Dataloader数据增强 2.3 CNN设计与训练nn.Mod…

YK人工智能(六)——万字长文学会基于Torch模型网络可视化

1. 可视化网络结构 随着深度神经网络做的的发展,网络的结构越来越复杂,我们也很难确定每一层的输入结构,输出结构以及参数等信息,这样导致我们很难在短时间内完成debug。因此掌握一个可以用来可视化网络结构的工具是十分有必要的…

堆的基本概念

1.1 堆的基本概念 虚拟机所在目录 E:\ctf\pwn-self 进入虚拟机的pwndocker环境 holyeyesubuntu:~$ pwd /home/holyeyes holyeyesubuntu:~$ sudo ./1run.sh IDA分析 int __fastcall main(int argc, const char **argv, const char **envp) { void *v4; // [rsp20h] [rbp-1…

RabbitMQ深度探索:前置知识

消息中间件: 消息中间件基于队列模式实现异步 / 同步传输数据作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合 传统的 HTTP 请求存在的缺点: HTTP 请求基于响应的模型,在高并发的情况下,客户端发送大量的请求…

JDK9新特性

文章目录 新特性:1.模块化系统使用模块化module-info.java:exports:opens:requires:provides:uses: 2.JShell启动Jshell执行计算定义变量定义方法定义类帮助命令查看定义的变量:/var…

合宙air001使用命令行烧写固件

起因: 做了个小板子给同事使用,但同事没有air001的arduino编译烧录环境,安装的话,对于没有接触过arduino的人有些复杂,所以想着能不能直接烧录编译好的固件; 经过: 在网上搜索相关教程&#…

manimgl安装

一、环境 笔记本 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammy二、安装miniconda3 manimgl基于python开发,为了防止将笔记本中已有的python环境破坏,因此…

Python aiortc API

本研究的主要目的是基于Python aiortc api实现抓取本地设备(摄像机、麦克风)媒体流实现Web端预览。本文章仅仅描述实现思路,索要源码请私信我。 demo-server解耦 原始代码解析 http服务器端 import argparse import asyncio import json…

编程AI深度实战:大模型哪个好? Mistral vs Qwen vs Deepseek vs Llama

随着开源 LLM 的发展,越来越多的模型变得专业化,“代码”LLM 变得非常流行。这些 LLM 旨在比其 “常识” 对应物更小,但旨在超越更大的通用模型的编码性能。 这些模型以极低的成本提供大型模型的功能,进一步使本地 LLM 空间民主化…

DeepSeek:全栈开发者视角下的AI革命者

目录​​​​​​​ DeepSeek:全栈开发者视角下的AI革命者 写在前面 一、DeepSeek的诞生与定位 二、DeepSeek技术架构的颠覆性突破 1、解构算力霸权:从MoE架构到内存革命 2、多模态扩展的技术纵深 3、算法范式的升维重构 4、重构AI竞争规则 三、…

SQL入门到精通 理论+实战 -- 在 MySQL 中学习SQL语言

目录 一、环境准备 1、MySQL 8.0 和 Navicat 下载安装 2、准备好的表和数据文件: 二、SQL语言简述 1、数据库基础概念 2、什么是SQL 3、SQL的分类 4、SQL通用语法 三、DDL(Data Definition Language):数据定义语言 1、操…

HTB:EscapeTwo[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用nmap对靶机…

一文讲解Java中的ArrayList和LinkedList

ArrayList和LinkedList有什么区别? ArrayList 是基于数组实现的,LinkedList 是基于链表实现的。 二者用途有什么不同? 多数情况下,ArrayList更利于查找,LinkedList更利于增删 由于 ArrayList 是基于数组实现的&#…

多无人机--强化学习

这个是我对于我的大创项目的构思,随着时间逐渐更新 项目概要 我们的项目平台来自挑战杯揭绑挂帅的无人机对抗项目,但是在由于时间原因,并未考虑强化学习,所以现在通过大创项目来弥补遗憾 我们项目分为三部分,分为虚…

龙芯+FreeRTOS+LVGL实战笔记(新)——16数码管驱动

本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了完善与优化,各位可以前往本人在B站的视频合集(图1所示)观看所有演示视频,合集首个视频链接为: https://www.bilibili.…

Day36-【13003】短文,数组的行主序方式,矩阵的压缩存储,对称、三角、稀疏矩阵和三元组线性表,广义表求长度、深度、表头、表尾等

文章目录 本次课程内容第四章 数组、广义表和串第一节 数组及广义表数组的基本操作数组的顺序存储方式-借用矩阵行列式概念二维数组C语言对应的函数-通常行主序方式 矩阵的压缩存储对称矩阵和三角矩阵压缩存储后,采用不同的映射函数稀疏矩阵-可以构成三元组线性表三…

[Python人工智能] 四十九.PyTorch入门 (4)利用基础模块构建神经网络并实现分类预测

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前文讲解PyTorch构建回归神经网络。这篇文章将介绍如何利用PyTorch构建神经网络实现分类预测,其是使用基础模块构建。前面我们的Python人工智能主要以TensorFlow和Keras为主,而现在最主流的深度学习框…

Java进阶14 TCP日志枚举

Java进阶14 TCP&日志&枚举 一、网络编程TCP Java对基于TCP协议得网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。 1、TCP协议发数据 1.1 构造方法 方法 说明 Socket(InetAddress address…

Java三十天速成(java进阶篇)

Day 15 一、集合框架 1、集合框架图 2、数据结构: ①、逻辑结构; 在计算机科学中,逻辑结构是指数据元素之间的关系,它描述了数据元素之间的逻辑联系,而不是它们在计算机内存中的物理存储方式。逻辑结构可以分为以下…