食品溯源合约 -- 智能合约实例
前提
Roles: 实现对用户地址的角色权限管控,添加、删除角色。
Producer: 生产商角色管控。
...
FoodInfoItem: 食品信息管控。生产商、中间商、超市添加食品信息。
Trace:食品溯源合约,主要负责对以上几个合约的统筹协作。
Roles
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;//角色库(管理所有角色地址)
// 1. 实现增加角色地址
// 2. 移除角色地址
// 3. 判断角色地址是否被授权
library Roles{struct Role{mapping (address =>bool) bearer;}// 在 Solidity 中,映射(mapping)不能在函数内部声明为局部变量,// 也不能在当前版本(0.8.0)中作为库(library)的成员变量。// 假如role 显示声明storage,那么算是合约中的状态变量,而且不能是memoryfunction add(Role storage role,address account) public { require(!has(role,account),"Roles:account already has role");role.bearer[account] = true;}function remove(Role storage role,address account) public {require(!has(role,account),"Roles:account has no role ");role.bearer[account] = false;}function has(Role storage role,address account) public view returns(bool){require(account != address(0),"Roles: account cannot be zero address");return role.bearer[account];}}
Producer
PS:这下面这三个都是代表角色,代码几乎一样的,看会这个,其他都会。
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
import "./Roles.sol";
/**
*@title Producer
*@dev
*/
contract Producer {using Roles for Roles.Role;event ProducerAdded(address indexed account);event ProducerRemoved(address indexed account);Roles.Role private _producers; // 使用这个相当于使用库constructor(address producer){ // 初始化给账户添加权限_addProducer(producer);}// 关于下面这几个函数为什么要拆分?提高代码可读性。modifier onlyProducer(){require(isProducer(msg.sender),"Producer:caller has no Producer role");_;}// 用户是否拥有权限function isProducer(address account) public view returns (bool) {return _producers.has(account);}function addProducer(address account) public onlyProducer {_addProducer(account); // 不是很理解,为什么设置只有生产者角色才能为地址添加生产者角色权限}function removeRroducer(address account) public {_removeProducer(account);}function _addProducer(address account) internal {_producers.add(account); // 我们看向Roles的add()其实还有一个参数,但是我们 using for 了那个参数就相当于 _producers本身emit ProducerAdded(account);}function _removeProducer(address account) internal {_producers.remove(account);emit ProducerRemoved(account);}}
Retailer
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
import "./Roles.sol";// 超市
contract Retailer {using Roles for Roles.Role;event RetailerAdded(address indexed account);event RetailerRemoved(address indexed account);Roles.Role private _retailers; // 使用这个相当于使用库constructor(address retailer){ // 初始化给账户添加权限_addRetailer(retailer);}// 关于下面这几个函数为什么要拆分?提高代码可读性。modifier onlyRetailer(){require(isRetailer(msg.sender),"Retailer:caller has no Retailer role");_;}// 用户是否拥有权限function isRetailer(address account) public view returns (bool) {return _retailers.has(account);}function addRetailer(address account) public onlyRetailer {_addRetailer(account); }function removeRroducer(address account) public {_removeRetailer(account);}function _addRetailer(address account) internal {_retailers.add(account); // 我们看向Roles的add()其实还有一个参数,但是我们 using for 了那个参数就相当于 _Retailers本身emit RetailerAdded(account);}function _removeRetailer(address account) internal {_retailers.remove(account);emit RetailerRemoved(account);}}
Distributor
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
import "./Roles.sol";
// 中间商
contract Distributor {using Roles for Roles.Role;event DistributorAdded(address indexed account);event DistributorRemoved(address indexed account);Roles.Role private _distributors; // 使用这个相当于使用库constructor(address distributor){ // 初始化给账户添加权限_addDistributor(distributor);}// 关于下面这几个函数为什么要拆分?提高代码可读性。modifier onlyDistributor(){require(isDistributor(msg.sender),"Distributor:caller has no Distributor role");_;}// 用户是否拥有权限function isDistributor(address account) public view returns (bool) {return _distributors.has(account);}function addDistributor(address account) public onlyDistributor {_addDistributor(account); }function removeRroducer(address account) public {_removeDistributor(account);}function _addDistributor(address account) internal {_distributors.add(account); // 我们看向Roles的add()其实还有一个参数,但是我们 using for 了那个参数就相当于 _Distributors本身emit DistributorAdded(account);}function _removeDistributor(address account) internal {_distributors.remove(account);emit DistributorRemoved(account);}}
FoodInfoItem
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
pragma experimental ABIEncoderV2;//食品信息管理合约
// 1. 保存食品基本信息:时间戳(流转过程中),用户名(流转过程中),用户地址信息(流转过程中),食品质量(流转过程中),食物名称,当前用户名称,质量,状态.
// 2. 对食品基本信息进行初始化
// 3. 实现两个方法:中间商添加食品信息;超市添加食品信息
// 4. 实现显示食品信息的方法contract FoodInfoItem {uint[] _timestamp; //保存食品流转过程中各个阶段的时间戳string[] _traceName; //保存食品流转过程各个阶段的用户名address[] _traceAddress; //保存食品流转过程各个阶段的用户地址信息(和用户一一对应)uint8[] _traceQuality; //保存食品流转过程中各个阶段的质量string _name; //食品名称string _currentTraceName; //当前用户名称uint8 _quality; //质量(0=优质 1=合格 2=不合格)uint8 _status; //状态(0:生产 1:分销 2:出售)address _owner;// 初始化食品,创建者是生产商constructor(string memory name,string memory traceName,uint8 quality,address producer) public {_name = name;_currentTraceName = traceName;_quality = quality;_owner = producer;_status = 0;// 不多说,看上面状态变量都能明白_timestamp.push(block.timestamp); _traceName.push(traceName);_traceAddress.push(producer);_traceQuality.push(quality);}// 中间商添加食品信息function addTraceInfoByDistributor(string memory traceName,uint8 quality,address distributor) public returns(bool){require(_status == 0, "FoddIndo: caller must be distributor");_currentTraceName = traceName;_quality = quality;_status = 1;_timestamp.push(block.timestamp); _traceName.push(traceName);_traceAddress.push(distributor);_traceQuality.push(quality);return true;}// 超市添加食品信息function addTraceInfoByRetailer(string memory traceName,uint8 quality,address retailer)public returns(bool){require(_status == 1, "FoddIndo: caller must be retailer");_currentTraceName = traceName;_quality = quality;_status = 2;_timestamp.push(block.timestamp); _traceName.push(traceName);_traceAddress.push(retailer);_traceQuality.push(quality);return true;}// 拿到食品流转的全部信息function getTraceInfo() public view returns(uint[] memory,string[] memory,address[] memory,uint8[] memory){return (_timestamp,_traceName,_traceAddress,_traceQuality);}// 拿到生产商一开始添加食品信息function getFood() public view returns(uint,string memory,address,uint8,string memory){return (_timestamp[0],_traceName[0],_traceAddress[0],_traceQuality[0],_name);}}
Trace
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
pragma experimental ABIEncoderV2; // 开启实验性功能,包括对map,数组的编码和解码等
import "./FoodInfoItem.sol";
import "./Distributor.sol";
import "./Producer.sol";
import "./Retailer.sol";//食品溯源合约(负责具体食品溯源信息的生成)
// 1.实现生产食品的方法(新建食品信息)
// 2.实现食品分销过程中增加溯源信息的接口
// 3.实现食品出售过程中增加溯源信息的接口
// 4.实现获取食品溯源信息接口contract Trace is Distributor,Producer,Retailer {mapping(uint256 => address) foods; //食品溯源id到 -> 具体食品溯源合约的映射表uint[] foodList; // 食品溯源id数组//构造函数初始化,一起把父类角色初始化constructor(address producer,address distributor,address retailer) Producer(producer) Distributor(distributor) Retailer(retailer) {}// 生产商调用,调用添加食品信息function newFood(string memory name,uint256 traceNumber, // 溯源idstring memory traceName,uint8 quality) public onlyProducer returns (address) {require(foods[traceNumber] == address(0), "Trace:traceNumber already exist"); // 检测溯源id对应食品合约是否已经存在,已存在id不能用。FoodInfoItem food = new FoodInfoItem( // 初始化食品合约name,traceName,quality,msg.sender);foods[traceNumber] = address(food); // 往映射表添加地址foodList.push(traceNumber); // 往食品溯源数组添加溯源idreturn address(food);}// 中间商调用,添加食品信息function addTraceInfoByDistributor(uint256 traceNumber,string memory traceName,uint8 quality) public onlyDistributor returns (bool) {require(foods[traceNumber] != address(0), "Trace:traceNumber does not exist"); // id 对应食品合约没存在,代表没食品returnFoodInfoItem(foods[traceNumber]).addTraceInfoByDistributor(traceName,quality,msg.sender); // 调用对应的食品合约方法}// 超市调用,添加食品信息function addTraceInfoByRetailer(uint256 traceNumber,string memory traceName,uint8 quality) public onlyRetailer returns (bool) {require(foods[traceNumber] != address(0), "Trace:traceNumber does not exist");returnFoodInfoItem(foods[traceNumber]).addTraceInfoByRetailer(traceName,quality,msg.sender);}// 拿到所有食品信息function getTraceInfo(uint256 traceNumber) public view returns (uint[] memory,string[] memory,address[] memory,uint8[] memory) {require(foods[traceNumber] != address(0), "Trace:traceNumber does not exist");return FoodInfoItem(foods[traceNumber]).getTraceInfo();}//拿到单条食品信息function getFood(uint256 traceNumber) public view returns (uint,string memory,address,uint8,string memory) {require(foods[traceNumber] != address(0), "Trace:traceNumber does not exist");return FoodInfoItem(foods[traceNumber]).getFood();}// 拿到全部食品的溯源id数组function getAllFood() public view returns (uint[] memory) {return foodList;}}
相关文章:
食品溯源合约 -- 智能合约实例
前提 Roles: 实现对用户地址的角色权限管控,添加、删除角色。 Producer: 生产商角色管控。 ... FoodInfoItem: 食品信息管控。生产商、中间商、超市添加食品信息。 Trace:食品溯源合约,主要负责对以上几个合约的统筹协作。 Roles // SPDX-License-Identifier: MIT pragm…...
SAP系统中二代增强提供了4中增强函数的查找方法
1 Introduction The second enhancement is used widely by sap .We can set break-point in the function . The function is in the SMOD FG. 2 Detail SAP系统中二代增强提供了4中增强函数的查找方法: MODX_ALL_ACTIVE_MENUENTRIES (菜单增强) MODX_FUNCTION…...
RabbitMQ-SpringBoot2
1.依赖引用 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2.配置文件 spring: rabbitmq: host: 192.168.2.17 port: 5672 usernam…...
MyBatis核心 - SqlSession如何通过Mapper接口生成Mapper对象
书接上文 MyBatis – 执行流程 我们通过SqlSession获取到了UserMapper对象,代码如下: // 获取SqlSession对象 SqlSession sqlSession sqlSessionFactory.openSession();// 执行查询操作 try {// 获取映射器接口UserMapper userMapper sqlSession.get…...
【Git】标签管理与Git Flow模型
目录 一、操作标签 二、推送标签 三、删除标签 四、Git Flow模型分支设计 一、操作标签 git tag # 查看有哪些标签 git tag [name] # 给最近一次commit打标签 git tag [name] [commitID] #给指定的commit打标签 git tag -a [name] -m desc # 打标签并添加描述 二、推送标…...
日志分析和流量分析
目录 [陇剑杯 2021]日志分析(问1) [陇剑杯 2021]日志分析(问2) [陇剑杯 2021]日志分析(问3) [陇剑杯 2021]简单日志分析(问1) [陇剑杯 2021]简单日志分析(问3&#…...
typescript基础之关键字type
TypeScript的type是一个关键字,用来定义一个类型别名https://www.typescripttutorial.net/typescript-tutorial/typescript-types/。类型别名可以给一个已有的类型起一个新的名字,或者组合多个类型成为一个新的类型。例如: // 给string类型起…...
无人机航测技术有何特点?主要应用在哪些方面?
无人机航测是航空摄影测量的一种,主要面向低空遥感领域,具有成本低、快速高效、适用范围广等特点。目前,无人机航测主要应用于地形测绘、城市数字化建设、工程建设等方面。 无人机航测技术的特点 1、作业成本低 传统的人工测量技术主要利用…...
24届近5年杭州电子科技大学自动化考研院校分析
今天给大家带来的是杭州电子科技大学控制考研分析 满满干货~还不快快点赞收藏 一、杭州电子科技大学 学校简介 杭州电子科技大学(Hangzhou Dianzi University),简称“杭电”,位于杭州市,是浙江省人民政…...
调整vscode
调整vscode 连wifi linux连接wifi...
Spring xml 方式整合mybatis 第三方框架
Spring整合MyBatis MyBatis提供了mybatis-spring.jar专门用于两大框架的整合。 ①:第一步: 导入MyBatis整合Spring的相关坐标; <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency><groupI…...
RabbitMQ(二) - RabbitMQ与消息发布确认与返回、消费确认
RabbitMQ消息确认 SpringBoot与RabbitMQ整合后,对RabbitClient的“确认”进行了封装、使用方式与RabbitMQ官网不一致; 消息发布确认 生产者给交换机发送消息后、若是不管了,则会出现消息丢失; 解决方案1: 交换机接受…...
操作指南 | 如何使用Chainlink喂价功能获取价格数据
Chainlink的去中心化预言机网络中的智能合约包含由运行商为其他智能合约(DApps)使用或截取所持续更新的实施价格数据。其中有两个主要架构:喂价和基础要求模型。此教程将会展现如何在Moonbeam、Moonriver或是Moonbase Alpha测试网上使用喂价功…...
Pandaer的iPhone手机壳
哇塞,Pandaer的设计太棒了!手机壳的花样多到让我眼花缭乱,好多系列设计都很有意思,让人有集齐的冲动。我最近入手了几个iPhone的手机壳,它有亮色和透明的款式,亮色的壳内部也是亮的,因为手机壳全…...
将自己的网站免费发布到互联网上【无需公网IP】
作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...
浅谈 Python中if __name__ == ‘__main__‘:的工作原理
为了理解if __name__ __main__:的工作原理,我们需要先了解Python中的特殊变量__name__。 每个Python模块都有一个内置的变量__name__。这个变量的值取决于如何执行模块: 如果模块是被直接运行的(例如,你使用命令python myscrip…...
【力扣】344. 反转字符串 <首尾指针>
【力扣】344. 反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1: 输入:s …...
Kubectl 详解
目录 陈述式资源管理方法:项目的生命周期:创建-->发布-->更新-->回滚-->删除声明式管理方法: 陈述式资源管理方法: kubernetes 集群管理集群资源的唯一入口是通过相应的方法调用 apiserver 的接口kubectl 是官方的CL…...
华为OD面试记录
The experience of applying for software test engineer(Dispatcher) 记录保存 招聘岗位: 测试工程师 Base:西安 华为面试流程如下: 流程名内容机试三题,总分400分,最后一道题200分人力资源面试询问私人问题,不谈薪资一面技术面二面技术面主管问项目…...
电源控制--品质因素Q值全解
什么是品质因素Q值? 在电源控制中,品质因素 Q 值通常用于描述电源滤波器的性能。电源滤波器用于减小电源中的噪声和干扰,以提供干净稳定的电源供应给电子设备。 品质因素 Q 值在电源滤波器中表示滤波器的带宽和中心频率之比,用于…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
