Solidity Smart Contract Example Development (2) (Explanation + Notes) - Food Traceability

General project requirements

Create three roles: producer, distributor, and retailer, and use the three roles to chain up the production, distribution, and retail of products, and be able to find out the full information on the chain. Includes the timestamp of each transaction, the transaction name of each transaction, the transaction address of each transaction, the food quality of each transaction, the name of the food, the name of the current transaction, the address of the current transaction, the food quality of the current transaction, the current Transaction status, etc.

Operating environment: remix (version 0.8.13)

Roles.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

library Roles{
    struct Role{
        mapping (address => bool) bearer;
    }

    //判断地址是否存在
    function has(Role storage role,address amount) internal  view returns (bool){
        require(amount != address(0));//判断地址不为空
        return role.bearer[amount];//返回一个布尔值
    }

    //添加角色
    function add(Role storage role,address amount) internal {
        require(!has(role, amount));
        role.bearer[amount] = true;
    }
    /**这个函数用于向特定角色添加成员。它接受一个 Role 结构体和一个地址作为参数。在函数内部,
    它首先调用 has 函数检查地址是否已经具有该角色,
    如果没有,则将地址添加到映射中,并将其值设置为 true,表示该地址拥有该角色。
    */

    //删除角色
    function remove(Role storage role,address amount) internal {
        require(has(role, amount));
        role.bearer[amount] = false;
    }

    /**
    这个函数用于从特定角色中移除成员。它接受一个 Role 结构体和一个地址作为参数。
    在函数内部,它首先调用 has 函数检查地址是否具有该角色,
    如果是,则将地址从映射中移除,并将其值设置为 false,表示该地址不再拥有该角色。
    */
}

Producer.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./Roles.sol";


contract Producer{
    using Roles for Roles.Role;
    Roles.Role private _produce;



    event  producerAdded(address amount);
    event producerRemoved(address amount);

    constructor(address produce) public {
        _addProducer(produce);

    }

    function _addProducer(address amount) internal {
        _produce.add(amount);
        emit producerAdded(amount);
    }

    function _removeProducer(address amount) internal {
        _produce.remove(amount);
        emit producerRemoved(amount);
    }

    function isProducer(address amount ) public view returns (bool){
        return  _produce.has(amount);
    }

    modifier onlyProducer(){
        require(isProducer(msg.sender),"you are not deployer");
        _;
    }

    function addProducer(address amount) public onlyProducer{
        _addProducer(amount);
    }

    /**
    这个函数用于将调用者从生产商角色中移除。
    任何人都可以调用此函数来将自己从生产商角色中移除。它调用了 _removeProducer 函数来执行实际的移除操作。
    */
    function removeProducer() public  {
        _removeProducer(msg.sender);

    }
}

Distributor.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./Roles.sol";

contract Distributor{
    using Roles for Roles.Role;
    Roles.Role private  _distributor;


    event distributorAdded(address amount);
    event distributorRemoved(address amount);

    constructor(address distributor){
        _addDistributor(distributor);
 
    }

    function _addDistributor(address amount) internal {
        _distributor.add(amount);
        emit  distributorAdded(amount);
    }

    function _removeDistributor(address amount) internal {
        _distributor.remove(amount);
        emit  distributorRemoved(amount);
    }

    function isDistributor(address amount) public view  returns (bool){
        return _distributor.has(amount);
    } 

    modifier onlyDistributor(){
        require(isDistributor(msg.sender),"you are not deployer");
        _;
    }

    function addDistributor(address amount) public  onlyDistributor{
        _addDistributor(amount);
    }

    function removeDistributor() public {
        _removeDistributor(msg.sender);
    } 
}

Retailer.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./Roles.sol";

contract Retailer{
    using Roles for Roles.Role;
    Roles.Role private  _retailer;


    event retailerAdded(address amount);
    event retailerRemoved(address amount);

    constructor(address Retailer) {
        _addRetalier(Retailer);
 
    }
    function _addRetalier(address amount) internal {
        _retailer.add(amount);
        emit  retailerAdded(amount);
    }

    function _removeRetailer(address amount) internal {
        _retailer.remove(amount);
        emit  retailerRemoved(amount);
    }

    function isRetailer(address amount) public view  returns (bool){
        return _retailer.has(amount);
    }

    modifier onlyRetailer() {
        require(isRetailer(msg.sender),"you are not deployer");
        _;
    }

    function addRetailer(address amount) public  {
        _addRetalier(amount);
    }

    function removeRetailer() public {
        _removeRetailer(msg.sender);
    }
}

FoodInfoItem.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract FoodInfoItem{
    uint256[] _timestamp;  //时间戳
    string[]  _traceName;  //交易名称
    address[] _traceAddress;  //交易地址
    uint8[] _traceQuality;  //交易食品名称
    string _name;  //食品名称
    string _currentName;  //当前交易名称
    address _currentAddress;  //当前交易地址
    uint8 _currentQuality;  //当前交易质量 0 优质 1  合格  2 不合格
    uint8 _status;  //当前交易状态 0 生产 1 分销 2 销售
    address owner;


    constructor(string memory name, string memory traceName, address traceAddress,uint8 quality) public {
        _timestamp.push(block.timestamp);
        _traceName.push(traceName);
        _traceAddress.push(traceAddress);
        _traceQuality.push(quality);
        _name = name;
        _currentName = traceName;
        _currentAddress = traceAddress;
        _currentQuality = quality;
        _status = 0;
        owner = msg.sender;
    } 

    function addFoodByDistributor(string memory traceName, address traceAddress,uint8 quality) public  returns(bool) {
        require(_status == 0 ,"this is not status 0");
        _timestamp.push(block.timestamp);
        _traceName.push(traceName);
        _traceAddress.push(traceAddress);
        _traceQuality.push(quality);
        _currentName = traceName;
        _currentAddress = traceAddress;
        _currentQuality = quality;
        _status = 1;
        return true;
    }

    function addFoodByRetailer(string memory traceName, address traceAddress,uint8 quality) public  returns(bool){
        require(_status == 1 ,"this is not status 0");
        _timestamp.push(block.timestamp);
        _traceName.push(traceName);
        _traceAddress.push(traceAddress);
        _traceQuality.push(quality);
        _currentName = traceName;
        _currentAddress = traceAddress;
        _currentQuality = quality;
        _status = 2;
        return true;
    }

    //返回食品的信息
    function getFoodInfo() public  view returns (uint256,string memory,string memory,uint8,address,uint8){
        return (block.timestamp,_name,_currentName,_currentQuality,_currentAddress,_status);
    }

    //返回新增食品的信息农场
    function getFoodInfoNew() public view returns (uint256,string memory,string memory,address,uint8){
        return (block.timestamp,_name,_traceName[0],_traceAddress[0],_traceQuality[0]);
    }

    //返回通过分销商的信息
    function getFoodInfoByDistributor() public view returns (uint256,string memory,string memory,string memory,address,uint8){
        return (block.timestamp,_name,_traceName[0],_traceName[1],_traceAddress[1], _traceQuality[1]);
    }

    //返回通过零售商的信息
    function getFoodInfoByRetailer() public view returns (uint256,string memory, string memory,string memory,string memory, address,uint8){
        return (_timestamp[0],_name,_traceName[0],_traceName[1],_traceName[2],_traceAddress[2],_traceQuality[2]);
    }

    function getFoodInfoByRoles() public view  returns (uint256,address[] memory,uint8[] memory){
        return (_timestamp[0],_traceAddress,_traceQuality);
    }

    function getFoodInfoByAll() public view returns (string memory,uint256,string memory,uint8,uint256,string memory,uint8,uint256,string memory,uint8){
        return (_name,_timestamp[0],_traceName[0],_traceQuality[0],_timestamp[1],_traceName[1],_traceQuality[1],_timestamp[2],_traceName[2],_traceQuality[2]);
    }
}

Trace.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./Roles.sol";
import "./Producer.sol";
import "./Distributor.sol";
import "./Retailer.sol";
import "./FoodInfoItem.sol";

contract Trace is Producer,Distributor,Retailer{
    mapping (uint256 => address) foods;
    uint256[] foodlist;
    address public  owner;
    
    constructor(address producer,address distributor,address retailer) public Producer(producer) Distributor(distributor) Retailer(retailer){
        owner = msg.sender;
    }

    function newFood(uint256 traceNumber,string memory name,string memory traceName, uint8 quality) public onlyProducer returns (FoodInfoItem){
        require(foods[traceNumber]==address(0),"address is not exist");
        FoodInfoItem food = new FoodInfoItem(name,traceName,msg.sender,quality);
        foods[traceNumber] = address(food);
        foodlist.push(traceNumber);
        return food;
    }

    function addFoodByDistributor(uint256 traceNumber,string memory traceName,uint8 quality) public onlyDistributor returns (bool){
        require(foods[traceNumber] != address(0),"address is 0");
        return FoodInfoItem(foods[traceNumber]).addFoodByDistributor(traceName,msg.sender, quality);
    }

    function addFoodByRetailer(uint256 traceNumber, string memory traceName, uint8 quality) public  onlyRetailer returns (bool){
        require(foods[traceNumber] != address(0),"address is 0");
        return FoodInfoItem(foods[traceNumber]).addFoodByRetailer(traceName, msg.sender, quality);
    }

    //当前食品溯源
    function getFoodInfo(uint256 traceNumber) public view returns (uint256,string memory,string memory,uint8,address,uint8){
        return FoodInfoItem(foods[traceNumber]).getFoodInfo();
    }

    //农场溯源
    function getFoodInfoByNew(uint256 traceNumber) public view returns (uint256,string memory,string memory,address,uint8) {
        return FoodInfoItem(foods[traceNumber]).getFoodInfoNew();
    }

    //分销商溯源
    function getFoodInfoByDistributor(uint256 traceNumber) public view returns (uint256,string memory,string memory,string memory,address,uint8) {
        return FoodInfoItem(foods[traceNumber]).getFoodInfoByDistributor();
    }

    //零售商溯源
    function getFoodInfoRetailer(uint256 traceNumber) public view returns (uint256,string memory, string memory,string memory,string memory, address,uint8) {
        return FoodInfoItem(foods[traceNumber]).getFoodInfoByRetailer();
    }

    //三个阶段溯源
    function getFoodInfoByRoles(uint256 traceNumber) public view returns (uint256,address[] memory,uint8[] memory){
        return FoodInfoItem(foods[traceNumber]).getFoodInfoByRoles();
    }

    //消费者整体溯源
    function getFoodInfoByAll(uint256 traceNumber) public view returns (string memory,uint256,string memory,uint8,uint256,string memory,uint8,uint256,string memory,uint8) {
        return FoodInfoItem(foods[traceNumber]).getFoodInfoByAll();
    }

    //获取所有商品
    function getAllFood() public view returns (uint256[] memory){
        require(msg.sender == owner,"you are not deployer");
        return foodlist;
    }

}

Compile and deploy the final result

 

If you don’t understand, you can leave a message in the comment area directly. I will reply.

Guess you like

Origin blog.csdn.net/m0_72435337/article/details/131614571