当前位置: 首页 > 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;用于…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

Python环境安装与虚拟环境配置详解

本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南&#xff0c;适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者&#xff0c;都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.

报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符&#xff0c;最后运行&#xff1a;npm run lint --fix...

轻量安全的密码管理工具Vaultwarden

一、Vaultwarden概述 Vaultwarden主要作用是提供一个自托管的密码管理器服务。它是Bitwarden密码管理器的第三方轻量版&#xff0c;由国外开发者在Bitwarden的基础上&#xff0c;采用Rust语言重写而成。 &#xff08;一&#xff09;Vaultwarden镜像的作用及特点 轻量级与高性…...