编译器
0.8.24+commit.e11b9ed9
文件 1 的 5:Authorized.sol
pragma solidity ^0.8.17;
import { IAuthorized } from "./interfaces/IAuthorized.sol";
abstract contract Authorized is IAuthorized {
constructor() {
owner = msg.sender;
}
address private owner;
mapping (address => bool) private authorizedAdmins;
mapping (address => bool) private authorizedOperators;
modifier onlyOwner() {
if (msg.sender != owner) {
revert Unauthorized();
}
_;
}
modifier onlyAuthorizedAdmin() {
if (msg.sender != owner && !authorizedAdmins[msg.sender]) {
revert Unauthorized();
}
_;
}
modifier onlyAuthorizedOperator() {
if (msg.sender != owner && !authorizedAdmins[msg.sender] && !authorizedOperators[msg.sender]) {
revert Unauthorized();
}
_;
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Authorized System: New owner cannot be null");
require(newOwner != owner, "Authorized System: New owner cannot be the same as old owner");
require(!authorizedOperators[owner], "Authorized System: Owner cannot be an operator");
owner = newOwner;
}
function setAuthorizedAdmin(address _admin, bool status) public virtual onlyAuthorizedAdmin {
require(_admin != address(0), "Authorized System: Admin address cannot be null");
require(!authorizedOperators[_admin], "Authorized System: Admin cannot be an operator");
authorizedAdmins[_admin] = status;
emit SetAdmin(_admin);
}
function setAuthorizedOperator(address _operator, bool status) public virtual onlyAuthorizedAdmin {
require(_operator != address(0), "Authorized System: Operator address cannot be null");
require(!authorizedAdmins[_operator], "Authorized System: Operator cannot be an admin");
authorizedOperators[_operator] = status;
emit SetOperator(_operator);
}
function getAuthorizedAdmin(address _admin) public view virtual returns (bool) {
return authorizedAdmins[_admin];
}
function getAuthorizedOperator(address _operator) public view virtual returns (bool) {
return authorizedOperators[_operator];
}
function getOwner() public view virtual override returns (address) {
return owner;
}
}
文件 2 的 5:IAuthorized.sol
pragma solidity ^0.8.17;
interface IAuthorized {
error Unauthorized();
event SetAdmin(address indexed admin);
event SetOperator(address indexed operator);
event SetAuthOperator(address indexed authOperator);
function transferOwnership(address newOwner) external;
function setAuthorizedAdmin(address _admin, bool status) external;
function setAuthorizedOperator(address _operator, bool status) external;
function getAuthorizedAdmin(address _admin) external view returns (bool);
function getAuthorizedOperator(address _operator) external view returns (bool);
function getOwner() external view returns (address);
}
文件 3 的 5:IPayments.sol
pragma solidity ^0.8.24;
interface IPayments {
struct Service {
bytes32 serviceId;
uint256 pricePerItem;
bool active;
}
struct Invoice {
address user;
Service service;
uint256 qty;
uint256 total;
uint256 timestamp;
}
event ServiceAdded(bytes32 serviceId, string name, uint256 price);
event ServiceSet(bytes32 serviceId, bool active);
event ServicePaid(
bytes32 projectId,
address contractAddress,
bytes32 serviceId,
address user,
uint256 amount,
uint256 timestamp
);
event ServiceWithdraw(
bytes32 projectId,
address contractAddress,
bytes32 serviceId,
uint256 amount
);
error ServiceNotActive(bytes32 serviceId);
error InvalidTotalAmount();
error ServiceAlreadyPaid(
bytes32 projectId,
address contractAddress,
bytes32 serviceId
);
function addService(bytes32 _serviceId, uint256 _pricePerItem) external;
function setService(bytes32 _serviceId, bool _active) external;
function payService(
bytes32 _projectId,
address _contract,
bytes32 _serviceId,
uint256 _qty
) external payable;
function withdraw(
bytes32 _projectId,
address _contract,
bytes32 _serviceId,
address payable _to
) external;
function withdrawAll(address payable _to) external;
}
文件 4 的 5:Payments.sol
pragma solidity ^0.8.24;
import {IPayments} from "../interfaces/marketplace/IPayments.sol";
import {Authorized} from "@privylabs/authorized/contracts/Authorized.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract Payments is IPayments, Authorized, ReentrancyGuard {
mapping(bytes32 => Service) public services;
mapping(bytes32 => mapping(address => mapping(bytes32 => Invoice[])))
public invoices;
constructor() {}
function addService(
bytes32 _serviceId,
uint256 _pricePerItem
) public onlyAuthorizedOperator {
services[_serviceId] = Service(_serviceId, _pricePerItem, false);
}
function setService(
bytes32 _serviceId,
bool _active
) public onlyAuthorizedOperator {
services[_serviceId].active = _active;
}
function payService(
bytes32 _projectId,
address _contract,
bytes32 _serviceId,
uint256 _qty
) public payable nonReentrant {
if (!services[_serviceId].active) revert ServiceNotActive(_serviceId);
uint256 total = services[_serviceId].pricePerItem * _qty;
if (msg.value != total) revert InvalidTotalAmount();
Invoice memory invoice = Invoice(
msg.sender,
services[_serviceId],
_qty,
total,
block.timestamp
);
invoices[_projectId][_contract][_serviceId].push(invoice);
emit ServicePaid(
_projectId,
_contract,
_serviceId,
msg.sender,
total,
block.timestamp
);
}
function withdraw(
bytes32 _projectId,
address _contract,
bytes32 _serviceId,
address payable _to
) public onlyAuthorizedAdmin {
Invoice[] memory _invoices = invoices[_projectId][_contract][
_serviceId
];
uint256 total = 0;
for (uint256 i = 0; i < _invoices.length; i++) {
total += _invoices[i].total;
}
_to.transfer(total);
emit ServiceWithdraw(_projectId, _contract, _serviceId, total);
}
function withdrawAll(address payable _to) public onlyAuthorizedAdmin {
_to.transfer(address(this).balance);
}
}
文件 5 的 5:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
{
"compilationTarget": {
"contracts/marketplace/Payments.sol": "Payments"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidTotalAmount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"bytes32","name":"projectId","type":"bytes32"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"ServiceAlreadyPaid","type":"error"},{"inputs":[{"internalType":"bytes32","name":"serviceId","type":"bytes32"}],"name":"ServiceNotActive","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"ServiceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"projectId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ServicePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"ServiceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"projectId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ServiceWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"SetAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authOperator","type":"address"}],"name":"SetAuthOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"SetOperator","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_serviceId","type":"bytes32"},{"internalType":"uint256","name":"_pricePerItem","type":"uint256"}],"name":"addService","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"getAuthorizedAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"getAuthorizedOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"invoices","outputs":[{"internalType":"address","name":"user","type":"address"},{"components":[{"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct IPayments.Service","name":"service","type":"tuple"},{"internalType":"uint256","name":"qty","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_projectId","type":"bytes32"},{"internalType":"address","name":"_contract","type":"address"},{"internalType":"bytes32","name":"_serviceId","type":"bytes32"},{"internalType":"uint256","name":"_qty","type":"uint256"}],"name":"payService","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"services","outputs":[{"internalType":"bytes32","name":"serviceId","type":"bytes32"},{"internalType":"uint256","name":"pricePerItem","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setAuthorizedAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setAuthorizedOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_serviceId","type":"bytes32"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setService","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_projectId","type":"bytes32"},{"internalType":"address","name":"_contract","type":"address"},{"internalType":"bytes32","name":"_serviceId","type":"bytes32"},{"internalType":"address payable","name":"_to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]