当前位置: 首页 > news >正文

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

 

相关文章:

solidity高阶 -- 调用接口合约

在区块链开发中,Solidity 是一种广泛使用的智能合约编程语言,而接口合约(Interface)是 Solidity 中一个非常重要的概念。它为智能合约之间的交互提供了一种标准化的方式,使得合约之间的调用更加灵活、安全且易于管理。…...

若依框架使用(低级)

克隆源码 浏览器搜索若依,选择 RuoYi-Vue RuoYi-Vue RuoYi-Vue 重要的事情说三遍,进入gitee 下面这个页面(注意红色框起来的部分) 进入Gitee进行下载 我下载的是最新的springboot3 下载好后我们可以选择一个文件夹&#xff0…...

找不到 MSVCP120.dll

msvcr120.dll msvcr120.dll 是 Microsoft Visual C Redistributable 的一部分,属于 Visual Studio 2013(VC 12.0)的运行时组件。它的重要性取决于你运行的应用程序是否需要它。 重要性 依赖库:如果某个程序是用 Visual Studio 2…...

AI软件栈:LLVM分析(三)

LLVM IR 文章目录 CFG线性IR 主要采用CFG与线性IR组合描述 CFG *关键在于基本块(Basic Block)的定义 线性IR *关键来自于SSA,单静态赋值...

openwebui入门

1 简介 ‌Open WebUI‌(网址是openwebui.com)是一个高度可扩展、功能强大且用户友好的自托管Web用户界面,专为完全离线操作设计,编程语言是python。它支持对接Ollama和OpenAI兼容的API的大模型。‌ Open WebUI‌在架构上是一种中…...

Spark--如何理解RDD

1、概念 rdd是对数据集的逻辑表示,本身并不存储数据,只是封装了计算逻辑,并构建执行计划,通过保存血缘关系来记录rdd的执行过程和历史(当一个rdd需要重算时,系统会根据血缘关系追溯到最初的数据源&#xff…...

CTFSHOW-WEB入门-PHP特性89-100

题目:web 89 题目:解题思路:这道题目涉及了两个函数:preg_match()和intval()简要介绍一下两个函数 preg_match()用于对字符串进行正则表达式的匹配&#xff0…...

[250204] Mistral Small 3:小巧、快速、强大 | asdf 0.16.0 发布:Golang 重写带来性能飞跃

目录 Mistral AI 发布开源模型 Mistral Small 3:小巧、快速、强大asdf 0.16.0 版本发布:Golang 重写带来性能飞跃! Mistral AI 发布开源模型 Mistral Small 3:小巧、快速、强大 法国人工智能初创公司 Mistral AI 发布了最新的开源…...

PySpark学习笔记5-SparkSQL

sparkSql的数据抽象有两种。 一类是data set适用于java和Scala 一类是data frame适用于java,Scala,python 将r d d转换为data frame #方式一 df spark.createDataFrame(rdd,schema[name,age]) #方式二 schema Structtype(). add(id,integertype(),nu…...

windows版的docker如何使用宿主机的GPU

windows版的docker使用宿主机的GPU的命令 命令如下 docker run -it --nethost --gpus all --name 容器名 -e NVIDIA_DRIVER_CAPABILITIEScompute,utility -e NVIDIA_VISIBLE_DEVICESall 镜像名效果 (transformer) rootdocker-desktop:/# python Python 3.9.0 (default, Nov 15 …...

Python爬虫:1药城店铺爬虫(完整代码)

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…...

代码随想录算法训练营打卡第55天:并查集相关问题;

Java并查集的模板 //并查集模板 class DisJoint{private int[] father;public DisJoint(int N) {father new int[N];for (int i 0; i < N; i){father[i] i;}}public int find(int n) {return n father[n] ? n : (father[n] find(father[n]));}public void join (int …...

K8S学习笔记-------1.安装部署K8S集群环境

1.修改为root权限 #sudo su 2.修改主机名 #hostnamectl set-hostname k8s-master01 3.查看网络地址 sudo nano /etc/netplan/01-netcfg.yaml4.使网络配置修改生效 sudo netplan apply5.修改UUID&#xff08;某些虚拟机系统&#xff0c;需要设置才能生成UUID&#xff09;#…...

云原生周刊:K8s引领潮流

开源项目推荐 KWOK KWOK&#xff08;Kubernetes WithOut Kubelet&#xff09;是一个开源项目&#xff0c;旨在提供一个轻量级的 K8s 集群模拟环境&#xff0c;允许用户在不依赖真实节点的情况下&#xff0c;本地模拟整个 K8s 集群。它通过模拟 Kubelet 和其他集群组件的行为&…...

C_位运算符及其在单片机寄存器的操作

C语言的位运算符用于直接操作二进制位&#xff0c;本篇简单结束各个位运算符的作业及其在操作寄存器的应用场景。 一、位运算符的简单说明 1、按位与运算符&#xff08;&&#xff09; 功能&#xff1a;按位与运算符对两个操作数的每一位执行与操作。如果两个对应的二进制…...

【算法篇】贪心算法

目录 贪心算法 贪心算法实际应用 一&#xff0c;零钱找回问题 二&#xff0c;活动选择问题 三&#xff0c;分数背包问题 将数组和减半的最小操作次数 最大数 贪心算法 贪心算法&#xff0c;是一种在每一步选择中都采取当前状态下的最优策略&#xff0c;期望得到全局最优…...

Selenium 浏览器操作与使用技巧——详细解析(Java版)

目录 一、浏览器及窗口操作 二、键盘与鼠标操作 三、勾选复选框 四、多层框架/窗口定位 五、操作下拉框 六、上传文件操作 七、处理弹窗与 alert 八、处理动态元素 九、使用 Selenium 进行网站监控 前言 Selenium 是一款非常强大的 Web 自动化测试工具&#xff0c;能够…...

ioDraw桌面版 v3.4.0发布!AI文生图,AI图生图,手绘风格一键转换!

流程图功能升级 AI 文生图&#xff1a; 用户现在能输入文字描述&#xff0c;让软件自动生成对应的流程图画面&#xff0c;减少了手动绘图的工作量&#xff0c;提高创作效率&#xff0c;比如输入 “项目开发流程”&#xff0c;软件可能就会生成包含需求分析、设计、开发、测试…...

深入理解Node.js_架构与最佳实践

1. 引言 1.1 什么是Node.js Node.js简介:Node.js是一个基于Chrome V8引擎的JavaScript运行时,用于构建快速、可扩展的网络应用。Node.js的历史背景和发展:Node.js最初由Ryan Dahl在2009年发布,旨在解决I/O密集型应用的性能问题。随着时间的推移,Node.js社区不断壮大,提供…...

安装和卸载RabbitMQ

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/SUWXdDb0UoCV86xP6b3c7qtMn6b 使用Ubuntu环境进行安装 一、安装Erlang 在安装RabbitMQ之前,我们需要先安装Erlang,RabbitMQ需要Erlang的语言支持 #安装Erlang sudo apt-get install erlang 在安装的过程中,会弹出一段信息,此…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...