Example: Physical Infrastructure Management Library
This library is designed to handle operations involved in infrastructure management, ensuring data integrity and facilitating integration with IoT data sources for real-time monitoring and decision-making. The modular and extensible nature of the library allows developers to customize and scale it according to their specific project requirements.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice This library provides reusable smart contract modules for managing physical infrastructure on the blockchain.
library InfrastructureManagement {
    struct Asset {
        string name;
        uint256 id;
        address owner;
        uint256 createdAt;
        uint256 updatedAt;
        bool active;
    }
    struct MaintenanceRecord {
        uint256 assetId;
        uint256 maintenanceDate;
        string description;
        address performedBy;
        bool completed;
    }
    struct ResourceAllocation {
        uint256 assetId;
        uint256 resourceId;
        uint256 quantity;
        uint256 allocatedAt;
        bool active;
    }
    struct EventRecord {
        uint256 assetId;
        uint256 timestamp;
        string eventType;
        string data;
    }
    struct UserAuthorization {
        address user;
        bool authorized;
    }
    event AssetCreated(uint256 assetId, string name, address owner);
    event AssetUpdated(uint256 assetId, string name, address owner, bool active);
    event AssetTransferred(uint256 assetId, address from, address to);
    event MaintenanceScheduled(uint256 assetId, uint256 maintenanceDate, string description, address performedBy);
    event MaintenanceCompleted(uint256 assetId, uint256 maintenanceDate, address performedBy);
    event ResourceAllocated(uint256 assetId, uint256 resourceId, uint256 quantity, uint256 allocatedAt);
    event ResourceDeallocated(uint256 assetId, uint256 resourceId, uint256 quantity, uint256 deallocatedAt);
    event EventRecorded(uint256 assetId, uint256 timestamp, string eventType, string data);
    event UserAuthorized(address user);
    event UserRevoked(address user);
    function createAsset(mapping(uint256 => Asset) storage assets, uint256 assetId, string memory name, address owner) public {
        require(assets[assetId].id == 0, "Asset already exists");
        assets[assetId] = Asset({
            name: name,
            id: assetId,
            owner: owner,
            createdAt: block.timestamp,
            updatedAt: block.timestamp,
            active: true
        });
        emit AssetCreated(assetId, name, owner);
    }
    function updateAsset(mapping(uint256 => Asset) storage assets, uint256 assetId, string memory name, address owner, bool active) public {
        require(assets[assetId].id != 0, "Asset does not exist");
        Asset storage asset = assets[assetId];
        asset.name = name;
        asset.owner = owner;
        asset.updatedAt = block.timestamp;
        asset.active = active;
        emit AssetUpdated(assetId, name, owner, active);
    }
    function transferAsset(mapping(uint256 => Asset) storage assets, uint256 assetId, address newOwner) public {
        require(assets[assetId].id != 0, "Asset does not exist");
        require(newOwner != address(0), "New owner is the zero address");
        Asset storage asset = assets[assetId];
        address previousOwner = asset.owner;
        asset.owner = newOwner;
        asset.updatedAt = block.timestamp;
        emit AssetTransferred(assetId, previousOwner, newOwner);
    }
    function scheduleMaintenance(mapping(uint256 => MaintenanceRecord[]) storage maintenanceRecords, uint256 assetId, uint256 maintenanceDate, string memory description, address performedBy) public {
        maintenanceRecords[assetId].push(MaintenanceRecord({
            assetId: assetId,
            maintenanceDate: maintenanceDate,
            description: description,
            performedBy: performedBy,
            completed: false
        }));
        emit MaintenanceScheduled(assetId, maintenanceDate, description, performedBy);
    }
    function completeMaintenance(mapping(uint256 => MaintenanceRecord[]) storage maintenanceRecords, uint256 assetId, uint256 maintenanceDate, address performedBy) public {
        MaintenanceRecord[] storage records = maintenanceRecords[assetId];
        for (uint256 i = 0; i < records.length; i++) {
            if (records[i].maintenanceDate == maintenanceDate && records[i].performedBy == performedBy && !records[i].completed) {
                records[i].completed = true;
                emit MaintenanceCompleted(assetId, maintenanceDate, performedBy);
                break;
            }
        }
    }
    function allocateResource(mapping(uint256 => ResourceAllocation[]) storage resourceAllocations, uint256 assetId, uint256 resourceId, uint256 quantity) public {
        resourceAllocations[assetId].push(ResourceAllocation({
            assetId: assetId,
            resourceId: resourceId,
            quantity: quantity,
            allocatedAt: block.timestamp,
            active: true
        }));
        emit ResourceAllocated(assetId, resourceId, quantity, block.timestamp);
    }
    function deallocateResource(mapping(uint256 => ResourceAllocation[]) storage resourceAllocations, uint256 assetId, uint256 resourceId, uint256 quantity) public {
        ResourceAllocation[] storage allocations = resourceAllocations[assetId];
        for (uint256 i = 0; i < allocations.length; i++) {
            if (allocations[i].resourceId == resourceId && allocations[i].quantity == quantity && allocations[i].active) {
                allocations[i].active = false;
                emit ResourceDeallocated(assetId, resourceId, quantity, block.timestamp);
                break;
            }
        }
    }
    function recordEvent(mapping(uint256 => EventRecord[]) storage eventRecords, uint256 assetId, string memory eventType, string memory data) public {
        eventRecords[assetId].push(EventRecord({
            assetId: assetId,
            timestamp: block.timestamp,
            eventType: eventType,
            data: data
        }));
        emit EventRecorded(assetId, block.timestamp, eventType, data);
    }
    function authorizeUser(mapping(address => UserAuthorization) storage userAuthorizations, address user) public {
        require(!userAuthorizations[user].authorized, "User already authorized");
        userAuthorizations[user] = UserAuthorization({
            user: user,
            authorized: true
        });
        emit UserAuthorized(user);
    }
    function revokeUser(mapping(address => UserAuthorization) storage userAuthorizations, address user) public {
        require(userAuthorizations[user].authorized, "User not authorized");
        userAuthorizations[user].authorized = false;
        emit UserRevoked(user);
    }
    function isUserAuthorized(mapping(address => UserAuthorization) storage userAuthorizations, address user) public view returns (bool) {
        return userAuthorizations[user].authorized;
    }
}
Explanation:
This Solidity library, InfrastructureManagement, provides essential functionalities to manage physical infrastructure assets, including:
- Functions to create and update assets with events for logging changes. 
- Functions to schedule and complete maintenance activities, recording relevant details and emitting events. 
- Functions to allocate and deallocate resources to assets, ensuring efficient resource management with event logging. 
Example of Usage:
This smart contract includes functions for asset creation, updating, scheduling maintenance, completing maintenance and resource allocation. It also incorporates access control mechanisms, detailed events and error handling for a robust and secure implementation.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./DePINFW/InfrastructureManagement.sol";
/// @title Physical Infrastructure Management Smart Contract
/// @notice This contract manages physical infrastructure assets, including their lifecycle, maintenance, and resource allocation.
contract PhysicalInfrastructureManager {
    using InfrastructureManagement for mapping(uint256 => InfrastructureManagement.Asset);
    using InfrastructureManagement for mapping(uint256 => InfrastructureManagement.MaintenanceRecord[]);
    using InfrastructureManagement for mapping(uint256 => InfrastructureManagement.ResourceAllocation[]);
    using InfrastructureManagement for mapping(uint256 => InfrastructureManagement.EventRecord[]);
    using InfrastructureManagement for mapping(address => InfrastructureManagement.UserAuthorization);
    mapping(uint256 => InfrastructureManagement.Asset) private assets;
    mapping(uint256 => InfrastructureManagement.MaintenanceRecord[]) private maintenanceRecords;
    mapping(uint256 => InfrastructureManagement.ResourceAllocation[]) private resourceAllocations;
    mapping(uint256 => InfrastructureManagement.EventRecord[]) private eventRecords;
    mapping(address => InfrastructureManagement.UserAuthorization) private userAuthorizations;
    address public admin;
    event AdminChanged(address indexed previousAdmin, address indexed newAdmin);
    event UnauthorizedAccess(address indexed caller);
    modifier onlyAdmin() {
        require(msg.sender == admin, "Caller is not the admin");
        _;
    }
    modifier onlyAuthorized() {
        require(userAuthorizations[msg.sender].authorized || msg.sender == admin, "Caller is not authorized");
        _;
    }
    constructor() {
        admin = msg.sender;
        emit AdminChanged(address(0), msg.sender);
    }
    function changeAdmin(address newAdmin) public onlyAdmin {
        require(newAdmin != address(0), "New admin is the zero address");
        emit AdminChanged(admin, newAdmin);
        admin = newAdmin;
    }
    function authorizeUser(address user) public onlyAdmin {
        userAuthorizations.authorizeUser(user);
    }
    function revokeUser(address user) public onlyAdmin {
        userAuthorizations.revokeUser(user);
    }
    function createAsset(uint256 assetId, string memory name, address owner) public onlyAuthorized {
        assets.createAsset(assetId, name, owner);
    }
    function updateAsset(uint256 assetId, string memory name, address owner, bool active) public onlyAuthorized {
        assets.updateAsset(assetId, name, owner, active);
    }
    function transferAsset(uint256 assetId, address newOwner) public onlyAuthorized {
        assets.transferAsset(assetId, newOwner);
    }
    function getAsset(uint256 assetId) public view returns (InfrastructureManagement.Asset memory) {
        return assets[assetId];
    }
    function scheduleMaintenance(uint256 assetId, uint256 maintenanceDate, string memory description, address performedBy) public onlyAuthorized {
        maintenanceRecords.scheduleMaintenance(assetId, maintenanceDate, description, performedBy);
    }
    function completeMaintenance(uint256 assetId, uint256 maintenanceDate, address performedBy) public onlyAuthorized {
        maintenanceRecords.completeMaintenance(assetId, maintenanceDate, performedBy);
    }
    function getMaintenanceRecords(uint256 assetId) public view returns (InfrastructureManagement.MaintenanceRecord[] memory) {
        return maintenanceRecords[assetId];
    }
    function allocateResource(uint256 assetId, uint256 resourceId, uint256 quantity) public onlyAuthorized {
        resourceAllocations.allocateResource(assetId, resourceId, quantity);
    }
    function deallocateResource(uint256 assetId, uint256 resourceId, uint256 quantity) public onlyAuthorized {
        resourceAllocations.deallocateResource(assetId, resourceId, quantity);
    }
    function getResourceAllocations(uint256 assetId) public view returns (InfrastructureManagement.ResourceAllocation[] memory) {
        return resourceAllocations[assetId];
    }
    function recordEvent(uint256 assetId, string memory eventType, string memory data) public onlyAuthorized {
        eventRecords.recordEvent(assetId, eventType, data);
    }
    function getEventRecords(uint256 assetId) public view returns (InfrastructureManagement.EventRecord[] memory) {
        return eventRecords[assetId];
    }
    function getAssetsByOwner(address owner) public view returns (InfrastructureManagement.Asset[] memory) {
        uint256 count;
        for (uint256 i = 0; i < 1e6; i++) {
            if (assets[i].owner == owner) {
                count++;
            }
        }
        InfrastructureManagement.Asset[] memory result = new InfrastructureManagement.Asset[](count);
        uint256 index;
        for (uint256 i = 0; i < 1e6; i++) {
            if (assets[i].owner == owner) {
                result[index] = assets[i];
                index++;
            }
        }
        return result;
    }
    function getActiveAssets() public view returns (InfrastructureManagement.Asset[] memory) {
        uint256 count;
        for (uint256 i = 0; i < 1e6; i++) {
            if (assets[i].active) {
                count++;
            }
        }
        InfrastructureManagement.Asset[] memory result = new InfrastructureManagement.Asset[](count);
        uint256 index;
        for (uint256 i = 0; i < 1e6; i++) {
            if (assets[i].active) {
                result[index] = assets[i];
                index++;
            }
        }
        return result;
    }
}
Explanation:
- The - InfrastructureManagementlibrary is imported and utilized within the contract to manage assets, track maintenance, allocate resources, and handle event logging.
- The contract defines an admin address and restricts certain functions to the admin using the - onlyAdminmodifier. Additionally, it introduces an- onlyAuthorizedmodifier, allowing both the admin and authorized users to perform restricted actions.
- An - UnauthorizedAccessevent is emitted if a non-admin attempts to perform restricted actions, ensuring transparency and security.- Functions for creating and updating assets, scheduling and completing maintenance, as well as allocating and deallocating resources, are restricted to the admin or authorized users. 
- Functions for retrieving assets, maintenance records, and resource allocations are available to all users, promoting transparency and accessibility. 
- Additional helper functions enable users to fetch assets by owner and list active assets, providing convenient access to relevant data. 
- Detailed events are emitted for administrative changes, asset transfers, maintenance activities, resource allocations, and unauthorized access attempts, enhancing traceability and auditing. 
- Proper error handling is implemented using - revertto ensure the contract behaves correctly in case of unauthorized access or invalid operations.
This smart contract demonstrates a secure and comprehensive approach to managing physical infrastructure assets on the blockchain, leveraging the reusable and extensible components provided by the InfrastructureManagement library.
Last updated
