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

食品溯源合约 -- 智能合约实例

前提

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中增强函数的查找方法&#xff1a; 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对象&#xff0c;代码如下&#xff1a; // 获取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]日志分析&#xff08;问1&#xff09; [陇剑杯 2021]日志分析&#xff08;问2&#xff09; [陇剑杯 2021]日志分析&#xff08;问3&#xff09; [陇剑杯 2021]简单日志分析&#xff08;问1&#xff09; [陇剑杯 2021]简单日志分析&#xff08;问3&#…...

typescript基础之关键字type

TypeScript的type是一个关键字&#xff0c;用来定义一个类型别名https://www.typescripttutorial.net/typescript-tutorial/typescript-types/。类型别名可以给一个已有的类型起一个新的名字&#xff0c;或者组合多个类型成为一个新的类型。例如&#xff1a; // 给string类型起…...

无人机航测技术有何特点?主要应用在哪些方面?

无人机航测是航空摄影测量的一种&#xff0c;主要面向低空遥感领域&#xff0c;具有成本低、快速高效、适用范围广等特点。目前&#xff0c;无人机航测主要应用于地形测绘、城市数字化建设、工程建设等方面。 无人机航测技术的特点 1、作业成本低 传统的人工测量技术主要利用…...

24届近5年杭州电子科技大学自动化考研院校分析

今天给大家带来的是杭州电子科技大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、杭州电子科技大学 学校简介 杭州电子科技大学&#xff08;Hangzhou Dianzi University&#xff09;&#xff0c;简称“杭电”&#xff0c;位于杭州市&#xff0c;是浙江省人民政…...

调整vscode

调整vscode 连wifi linux连接wifi...

Spring xml 方式整合mybatis 第三方框架

Spring整合MyBatis MyBatis提供了mybatis-spring.jar专门用于两大框架的整合。 ①&#xff1a;第一步&#xff1a; 导入MyBatis整合Spring的相关坐标&#xff1b; <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency><groupI…...

RabbitMQ(二) - RabbitMQ与消息发布确认与返回、消费确认

RabbitMQ消息确认 SpringBoot与RabbitMQ整合后&#xff0c;对RabbitClient的“确认”进行了封装、使用方式与RabbitMQ官网不一致&#xff1b; 消息发布确认 生产者给交换机发送消息后、若是不管了&#xff0c;则会出现消息丢失&#xff1b; 解决方案1&#xff1a; 交换机接受…...

操作指南 | 如何使用Chainlink喂价功能获取价格数据

Chainlink的去中心化预言机网络中的智能合约包含由运行商为其他智能合约&#xff08;DApps&#xff09;使用或截取所持续更新的实施价格数据。其中有两个主要架构&#xff1a;喂价和基础要求模型。此教程将会展现如何在Moonbeam、Moonriver或是Moonbase Alpha测试网上使用喂价功…...

Pandaer的iPhone手机壳

哇塞&#xff0c;Pandaer的设计太棒了&#xff01;手机壳的花样多到让我眼花缭乱&#xff0c;好多系列设计都很有意思&#xff0c;让人有集齐的冲动。我最近入手了几个iPhone的手机壳&#xff0c;它有亮色和透明的款式&#xff0c;亮色的壳内部也是亮的&#xff0c;因为手机壳全…...

将自己的网站免费发布到互联网上【无需公网IP】

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…...

浅谈 Python中if __name__ == ‘__main__‘:的工作原理

为了理解if __name__ __main__:的工作原理&#xff0c;我们需要先了解Python中的特殊变量__name__。 每个Python模块都有一个内置的变量__name__。这个变量的值取决于如何执行模块&#xff1a; 如果模块是被直接运行的&#xff08;例如&#xff0c;你使用命令python myscrip…...

【力扣】344. 反转字符串 <首尾指针>

【力扣】344. 反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&#xff1a;s …...

Kubectl 详解

目录 陈述式资源管理方法&#xff1a;项目的生命周期&#xff1a;创建-->发布-->更新-->回滚-->删除声明式管理方法&#xff1a; 陈述式资源管理方法&#xff1a; kubernetes 集群管理集群资源的唯一入口是通过相应的方法调用 apiserver 的接口kubectl 是官方的CL…...

华为OD面试记录

The experience of applying for software test engineer(Dispatcher) 记录保存 招聘岗位: 测试工程师 Base:西安 华为面试流程如下&#xff1a; 流程名内容机试三题,总分400分,最后一道题200分人力资源面试询问私人问题&#xff0c;不谈薪资一面技术面二面技术面主管问项目…...

电源控制--品质因素Q值全解

什么是品质因素Q值&#xff1f; 在电源控制中&#xff0c;品质因素 Q 值通常用于描述电源滤波器的性能。电源滤波器用于减小电源中的噪声和干扰&#xff0c;以提供干净稳定的电源供应给电子设备。 品质因素 Q 值在电源滤波器中表示滤波器的带宽和中心频率之比&#xff0c;用于…...

多模态跨语言翻译引擎实战指南:本地化部署与场景化应用

多模态跨语言翻译引擎实战指南&#xff1a;本地化部署与场景化应用 【免费下载链接】seamless-m4t-v2-large 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/seamless-m4t-v2-large 在全球化协作日益频繁的今天&#xff0c;跨语言翻译已成为打破沟通壁垒的核…...

运维系列【仅供参考】:【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧

【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧 【Docker】容器生命周期管理:从优雅停止到高效清理的实战技巧 摘要 1. 为什么需要关注容器生命周期管理? 2. 停止容器的艺术:从温柔到强硬 2.1 优雅停止的正确姿势 2.2 何时该用强制终止 2.3 暂停与恢复的妙用 …...

深入Linuxptp:ptp4l与E2E模式下的状态机与报文处理流程剖析

1. Linuxptp与ptp4l基础认知 第一次接触PTP协议时&#xff0c;我被那些专业术语搞得晕头转向。直到在实验室里用示波器抓到实际报文&#xff0c;才真正理解这个时间同步协议的精妙之处。Linuxptp作为开源实现&#xff0c;其中的ptp4l守护进程就像个尽职的交通警察&#xff0c;协…...

【衢州学院主办,上海交通大学协办 | IET出版(有ISSN号) | 往届两年已完成 EI 、 IEEE Xplore检索 | 大咖组委】第三届人工智能与电力系统国际学术会议(AIPS 2026)

第三届人工智能与电力系统国际学术会议&#xff08;AIPS 2026) 2026 3rd International Conference on Artificial Intelligence and Power System 大会官网&#xff1a;www.icaips.org【参会投稿】 大会时间&#xff1a;2026年5月22-24日 大会地点&#xff1a;中国-浙江-衢…...

如何利用Postiz实现高效社交媒体管理:AI驱动的智能调度解决方案

如何利用Postiz实现高效社交媒体管理&#xff1a;AI驱动的智能调度解决方案 【免费下载链接】clickvote &#x1f4e8; The ultimate social media scheduling tool, with a bunch of AI &#x1f916; 项目地址: https://gitcode.com/GitHub_Trending/cl/clickvote Pos…...

DriverStore Explorer:Windows驱动全生命周期管理的开源解决方案——解决驱动冗余与设备冲突的高效工具

DriverStore Explorer&#xff1a;Windows驱动全生命周期管理的开源解决方案——解决驱动冗余与设备冲突的高效工具 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer Windows系统中驱动程…...

告别编译!用OSGeo4W一键搞定QGIS 3.40.13二次开发环境(QtCreator配置详解)

告别编译&#xff01;用OSGeo4W一键搞定QGIS 3.40.13二次开发环境&#xff08;QtCreator配置详解&#xff09; 当你想快速验证一个QGIS插件创意或测试某个自定义功能时&#xff0c;最令人沮丧的莫过于花费数天时间搭建开发环境。传统QGIS二次开发需要从源码编译&#xff0c;光是…...

Ender3V2S1切片器脚本配置指南:优化3D打印效果的完整教程

Ender3V2S1切片器脚本配置指南&#xff1a;优化3D打印效果的完整教程 【免费下载链接】Ender3V2S1 This is optimized firmware for Ender3 V2/S1 3D printers. 项目地址: https://gitcode.com/gh_mirrors/en/Ender3V2S1 Ender3V2S1是一款备受欢迎的3D打印机&#xff0c…...

技术解析 | 【ECCV2022】MuLUT:多级查找表协同优化在图像超分中的高效实践

1. MuLUT技术背景与核心价值 图像超分辨率&#xff08;Super-Resolution&#xff09;技术一直是计算机视觉领域的热门研究方向&#xff0c;简单来说就是让低分辨率图像变清晰的过程。传统基于卷积神经网络&#xff08;CNN&#xff09;的方法虽然效果不错&#xff0c;但计算量大…...

探索marked:高性能Markdown解析的Web开发工具解决方案

探索marked&#xff1a;高性能Markdown解析的Web开发工具解决方案 【免费下载链接】marked A markdown parser and compiler. Built for speed. 项目地址: https://gitcode.com/gh_mirrors/ma/marked 在现代Web开发中&#xff0c;Markdown解析作为内容呈现的关键环节&am…...