// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @title Billing * @dev Smart contract for tracking billing and resource usage costs */ contract Billing { struct UsageRecord { string resourceId; string resourceType; uint256 startTime; uint256 endTime; uint256 cost; // Cost in smallest unit (wei-like) string currency; address billedTo; } struct Bill { address billedTo; uint256 periodStart; uint256 periodEnd; uint256 totalCost; string currency; bool paid; uint256 paidAt; } mapping(string => UsageRecord[]) public resourceUsage; mapping(address => Bill[]) public bills; mapping(string => uint256) public resourceCosts; event UsageRecorded( string indexed resourceId, address indexed billedTo, uint256 cost, uint256 timestamp ); event BillGenerated( address indexed billedTo, uint256 billId, uint256 totalCost, uint256 periodStart, uint256 periodEnd ); event BillPaid( address indexed billedTo, uint256 billId, uint256 paidAt ); /** * @dev Record resource usage and cost */ function recordUsage( string memory resourceId, string memory resourceType, uint256 startTime, uint256 endTime, uint256 cost, string memory currency, address billedTo ) public returns (bool) { UsageRecord memory record = UsageRecord({ resourceId: resourceId, resourceType: resourceType, startTime: startTime, endTime: endTime, cost: cost, currency: currency, billedTo: billedTo }); resourceUsage[resourceId].push(record); resourceCosts[resourceId] += cost; emit UsageRecorded(resourceId, billedTo, cost, block.timestamp); return true; } /** * @dev Generate a bill for a billing period */ function generateBill( address billedTo, uint256 periodStart, uint256 periodEnd ) public returns (uint256) { uint256 totalCost = 0; // Calculate total cost from all usage records in period // This is simplified - actual implementation would aggregate all resources uint256 billId = bills[billedTo].length; Bill memory bill = Bill({ billedTo: billedTo, periodStart: periodStart, periodEnd: periodEnd, totalCost: totalCost, currency: "USD", paid: false, paidAt: 0 }); bills[billedTo].push(bill); emit BillGenerated(billedTo, billId, totalCost, periodStart, periodEnd); return billId; } /** * @dev Mark a bill as paid */ function payBill(address billedTo, uint256 billId) public { require(billId < bills[billedTo].length, "Bill does not exist"); require(!bills[billedTo][billId].paid, "Bill already paid"); bills[billedTo][billId].paid = true; bills[billedTo][billId].paidAt = block.timestamp; emit BillPaid(billedTo, billId, block.timestamp); } /** * @dev Get total cost for a resource */ function getResourceTotalCost(string memory resourceId) public view returns (uint256) { return resourceCosts[resourceId]; } /** * @dev Get all bills for an address */ function getBills(address billedTo) public view returns (Bill[] memory) { return bills[billedTo]; } }