食品溯源合约 -- 智能合约实例
前提
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 值在电源滤波器中表示滤波器的带宽和中心频率之比,用于…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
