编译器
0.8.12+commit.f00d7308
文件 1 的 27:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 27:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 3 的 27:Companies.sol
pragma solidity ^0.8.12;
import "./Random.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Companies is AccessControl {
using Random for Random.Manifest;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint public constant SALARY_DECIMALS = 2;
uint public SALARY_MULTIPLIER = 100;
struct Company {
uint128 baseSalary;
uint128 capacity;
}
Company[60] companies;
uint16[60] indexes;
uint16[60] counts;
Random.Manifest private mainDeck;
mapping(uint => Random.Manifest) private specialDecks;
mapping(uint => uint) private specialCompanyIds;
uint specialCompanyIdFlag;
uint[] _tempArray;
mapping(uint => bool) managerIds;
mapping(uint => string) names;
event jobIDCreated (uint256 regularId, uint newJobId, uint companyId, address sender);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, tx.origin);
_grantRole(MINTER_ROLE, msg.sender);
names[0] = "RNN News";
names[1] = "AAAARP";
names[2] = "Petstore";
names[3] = "Foodtime";
names[4] = "Hats";
names[5] = "Bed Bath & Bodyworks";
names[6] = "Bugs Inc.";
names[7] = "Autoz";
names[8] = "Office Dept.";
names[9] = "Express";
names[10] = "Totally Wine";
names[11] = "Y'all";
names[12] = "5 O'clockville";
names[13] = "Nrfthrup Grrmng";
names[14] = "Mall Corp.";
names[15] = "Ice Creams";
names[16] = "Thanky Candles";
names[17] = "Hotella";
names[18] = "Berkshire Thataway";
names[19] = "Kopies";
names[20] = "Sprayers";
names[21] = "'Onuts";
names[22] = "Tax Inc.";
names[23] = "Khols";
names[24] = "Black Pebble";
names[25] = "Haircuts Inc.";
names[26] = "Global Gas";
names[27] = "Block";
names[28] = "Eyeglasses";
names[29] = "Books & Mags";
names[30] = "Meme";
names[31] = "Coin";
names[32] = "Wonder";
names[33] = "iSecurity";
names[34] = "Dairy Lady";
names[35] = "Big Deal MGMT";
names[36] = "Spotlight Talent";
names[37] = "Rock Solid Insurance";
names[38] = "Safe Shield Insurance";
names[39] = "Bit";
names[40] = "Whoppy Jrs.";
names[41] = "WGMI Inc.";
names[42] = "Global International";
names[43] = "N.E.X.T. Rugs";
names[44] = "Alpha Limited";
names[45] = "Best Shack";
names[46] = "Partners & Partners";
names[47] = "Boss E-systems";
names[48] = "Blockbusters";
names[49] = "Hexagon Research Group";
names[50] = "Crabby Shack";
names[51] = "Dollar Store";
names[52] = "UP Only";
names[53] = "Frito Pay";
names[54] = "Hot Pockets";
names[55] = "Spooky";
names[56] = "GM";
names[57] = "McDanny's";
names[58] = "Wendy's";
names[59] = "Party Place";
companies[0] = Company({ capacity : 212, baseSalary : 1950 });
companies[1] = Company({ capacity : 350, baseSalary : 1300 });
companies[2] = Company({ capacity : 120, baseSalary : 3725 });
companies[3] = Company({ capacity : 144, baseSalary : 3175 });
companies[4] = Company({ capacity : 168, baseSalary : 2375 });
companies[5] = Company({ capacity : 160, baseSalary : 2475 });
companies[6] = Company({ capacity : 100, baseSalary : 4400 });
companies[7] = Company({ capacity : 184, baseSalary : 2200 });
companies[8] = Company({ capacity : 500, baseSalary : 1025 });
companies[9] = Company({ capacity : 188, baseSalary : 2150 });
companies[10] = Company({ capacity : 140, baseSalary : 3250 });
companies[11] = Company({ capacity : 96, baseSalary : 4575 });
companies[12] = Company({ capacity : 50, baseSalary : 7550 });
companies[13] = Company({ capacity : 192, baseSalary : 2100 });
companies[14] = Company({ capacity : 92, baseSalary : 4750 });
companies[15] = Company({ capacity : 156, baseSalary : 2525 });
companies[16] = Company({ capacity : 176, baseSalary : 2275 });
companies[17] = Company({ capacity : 148, baseSalary : 3100 });
companies[18] = Company({ capacity : 200, baseSalary : 2050 });
companies[19] = Company({ capacity : 136, baseSalary : 3350 });
companies[20] = Company({ capacity : 204, baseSalary : 2000 });
companies[21] = Company({ capacity : 104, baseSalary : 4250 });
companies[22] = Company({ capacity : 218, baseSalary : 1900 });
companies[23] = Company({ capacity : 57, baseSalary : 6675 });
companies[24] = Company({ capacity : 196, baseSalary : 2075 });
companies[25] = Company({ capacity : 206, baseSalary : 2000 });
companies[26] = Company({ capacity : 210, baseSalary : 1950 });
companies[27] = Company({ capacity : 88, baseSalary : 4950 });
companies[28] = Company({ capacity : 214, baseSalary : 1925 });
companies[29] = Company({ capacity : 242, baseSalary : 1750 });
companies[30] = Company({ capacity : 124, baseSalary : 3625 });
companies[31] = Company({ capacity : 164, baseSalary : 2425 });
companies[32] = Company({ capacity : 116, baseSalary : 3850 });
companies[33] = Company({ capacity : 180, baseSalary : 2225 });
companies[34] = Company({ capacity : 172, baseSalary : 2325 });
companies[35] = Company({ capacity : 132, baseSalary : 3425 });
companies[36] = Company({ capacity : 152, baseSalary : 3025 });
companies[37] = Company({ capacity : 450, baseSalary : 1100 });
companies[38] = Company({ capacity : 600, baseSalary : 900 });
companies[39] = Company({ capacity : 112, baseSalary : 3975 });
companies[40] = Company({ capacity : 65, baseSalary : 5900 });
companies[41] = Company({ capacity : 76, baseSalary : 5500 });
companies[42] = Company({ capacity : 80, baseSalary : 5400 });
companies[43] = Company({ capacity : 84, baseSalary : 5150 });
companies[44] = Company({ capacity : 290, baseSalary : 1500 });
companies[45] = Company({ capacity : 108, baseSalary : 4100 });
companies[46] = Company({ capacity : 276, baseSalary : 1575 });
companies[47] = Company({ capacity : 400, baseSalary : 1200 });
companies[48] = Company({ capacity : 53, baseSalary : 7150 });
companies[49] = Company({ capacity : 300, baseSalary : 1475 });
companies[50] = Company({ capacity : 69, baseSalary : 5875 });
companies[51] = Company({ capacity : 72, baseSalary : 5650 });
companies[52] = Company({ capacity : 208, baseSalary : 1975 });
companies[53] = Company({ capacity : 128, baseSalary : 3525 });
companies[54] = Company({ capacity : 73, baseSalary : 5575 });
_tempArray = [
379, 391, 874, 1004, 1245, 1258, 1398, 1584, 1869, 1940, 1952, 2269, 2525, 2772, 3055, 3455, 3472, 3541,
3544, 3607, 3617, 4103, 4117, 4149, 4195, 4230, 4425, 5065, 5101, 5188,
4, 27, 48, 101, 136, 143, 157, 165, 172, 175, 226, 277, 388, 389, 418, 420, 444, 457, 493, 516, 518,
610, 638, 679, 681, 703, 743, 784, 867, 917, 959
];
parseSpecialRegIDs(55,_tempArray, 6250);
_tempArray = [
4466, 4684, 5342, 5437, 5932, 6838, 8043, 1175, 1274, 2005, 2497, 2592, 3063, 3285, 3300, 3316,
3454, 3983, 4541, 4856, 5171, 5219, 5265, 6643, 6719, 6982, 7147, 7303, 8012, 8944, 9644, 9822,
1013, 1032, 1042, 1084, 1127, 1142, 1196, 1234, 1279, 1295, 1296, 1297, 1310, 1323, 1356, 1390, 1405
];
parseSpecialRegIDs(56,_tempArray, 7700);
_tempArray = [
1617, 1808, 2149, 2632, 2833, 2847, 3301, 3524, 4822, 5139, 5735, 5906, 5946, 6451, 6663, 6762, 6831,
7278, 7519, 8365, 9434, 64, 488, 642, 946, 1014, 1650, 1823, 1949, 2178, 2593, 2992, 3070, 3331, 3745,
3944, 3961, 4030, 4070, 4090, 4197, 4244, 4719, 5551, 5761, 5779, 5895, 6044, 6048, 6276, 6599, 6681,
6832, 6873, 6889, 7124, 7550, 7975, 8130, 8579, 8599, 8689, 8784, 8794, 8903, 9053, 9205, 9254, 9407, 9994
];
parseSpecialRegIDs(57,_tempArray, 8250);
_tempArray = [
317, 456, 878, 1588, 2702, 2974, 3047, 3224, 3308, 3441, 4082, 4107, 5490, 5574, 5622, 6232, 6317,
6350, 6404, 6539, 7654, 7947, 7961, 8248, 8400, 8437, 8643, 8667, 8728, 9221, 9611, 9709, 9754, 9950
];
parseSpecialRegIDs(58,_tempArray, 7900);
_tempArray = [
5494, 5845, 6016, 6042, 6073, 6109, 6436, 6649, 7092, 7574, 7863, 8077, 8110, 8326, 8359, 8480, 8629,
8825, 9303, 9319, 9339, 9770, 9800, 9858, 9870,
1440, 1482, 1566, 1596, 1598, 1660, 1663, 1695, 1700,
1708, 1905, 1929, 1986, 2018, 2026, 2037, 2067, 2097, 2125, 2148, 2176, 2207, 2247, 2262, 2347, 2494
];
parseSpecialRegIDs(59,_tempArray, 7425);
_tempArray = [1617, 1808, 2149, 2632, 2833, 2847, 3301, 3524, 4822, 5139, 5735, 5906, 5946, 6451, 6663,
6762, 6831, 7278, 7519, 8365, 9434 ];
for (uint i = 0;i < _tempArray.length;i++){
managerIds[_tempArray[i]] = true;
}
specialCompanyIdFlag = 55;
uint jobCountNotSpecial = 0;
for (uint i = 0; i < specialCompanyIdFlag; i++) {
jobCountNotSpecial += companies[i].capacity;
}
mainDeck.setup(jobCountNotSpecial);
uint jobCountSpecial = 0;
for (uint i = specialCompanyIdFlag; i < numCompanies(); i++) {
jobCountSpecial += companies[i].capacity;
}
uint _startIndex = 0;
for (uint i = 0; i < numCompanies(); i++) {
indexes[i] = uint16(_startIndex);
_startIndex += companies[i].capacity;
}
}
function makeNewJob(uint _regularId) public onlyRole(MINTER_ROLE) returns (uint, uint) {
uint _pull;
uint _specialCompanyId = specialCompanyIds[_regularId];
uint _newJobId;
if (_specialCompanyId == 0) {
_pull = mainDeck.draw();
uint _companyId = getCompanyId(_pull);
counts[_companyId]++;
emit jobIDCreated(_regularId, add1(_pull), _companyId, msg.sender);
return (add1(_pull), _companyId);
} else {
_pull = specialDecks[_specialCompanyId].draw();
_newJobId = _pull + indexes[_specialCompanyId];
counts[_specialCompanyId]++;
emit jobIDCreated(_regularId, add1(_newJobId), _specialCompanyId, msg.sender);
return (add1(_newJobId), _specialCompanyId);
}
}
function updateCompany(uint _companyId, uint128 _baseSalary, string memory _name) public onlyRole(MINTER_ROLE) {
companies[_companyId].baseSalary = _baseSalary;
names[_companyId] = _name;
}
function setSalaryMultiplier(uint _basispoints) public onlyRole(MINTER_ROLE) {
SALARY_MULTIPLIER = _basispoints;
}
function getCount(uint _companyId) public view returns (uint) {
return counts[_companyId];
}
function getBaseSalary(uint _companyId) public view returns (uint) {
return companies[_companyId].baseSalary * SALARY_MULTIPLIER / 100;
}
function getSpread(uint _companyId) public pure returns (uint) {
uint _nothing = 12345;
return uint(keccak256(abi.encodePacked(_companyId + _nothing))) % 40;
}
function getCapacity(uint _companyId) public view returns (uint) {
return companies[_companyId].capacity;
}
function numCompanies() public view returns (uint) {
return companies.length;
}
function isManager(uint _regId) public view returns (bool) {
return managerIds[_regId];
}
function maxJobIds() public view returns (uint) {
uint _total = 0;
for (uint i = 0; i < numCompanies(); i++) {
_total += companies[i].capacity;
}
return _total;
}
function getName(uint _companyId) public view returns (string memory) {
return names[_companyId];
}
function getCompanyId(uint _jobId) internal view returns (uint) {
uint _numCompanies = companies.length;
uint i;
for (i = 0; i < _numCompanies -1; i++) {
if (_jobId >= indexes[i] && _jobId < indexes[i+1])
break;
}
return i;
}
function parseSpecialRegIDs(uint _companyId, uint[] memory _ids, uint _baseSalary) internal {
for (uint i = 0;i < _ids.length; i++) {
specialCompanyIds[_ids[i]] = _companyId;
}
companies[_companyId] = Company({ capacity : uint128(_ids.length), baseSalary : uint128(_baseSalary) });
specialDecks[_companyId].setup(_ids.length);
}
function add1(uint _x) internal pure returns (uint) {
return _x + 1;
}
}
文件 4 的 27:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 5 的 27:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 6 的 27:ERC2981.sol
pragma solidity ^0.8.0;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
external
view
virtual
override
returns (address, uint256)
{
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
function _setTokenRoyalty(
uint256 tokenId,
address receiver,
uint96 feeNumerator
) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}
文件 7 的 27:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 8 的 27:ERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId;
_ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId;
_allTokensIndex[lastTokenId] = tokenIndex;
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
文件 9 的 27:ERC721Royalty.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../common/ERC2981.sol";
import "../../../utils/introspection/ERC165.sol";
abstract contract ERC721Royalty is ERC2981, ERC721 {
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
_resetTokenRoyalty(tokenId);
}
}
文件 10 的 27:FinanceDept.sol
pragma solidity ^0.8.12;
import "./Salaries.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
interface JobsI {
function setTimestamp(uint _jobId, uint _timestamp) external;
function sameOwner(uint _jobId) external view returns (bool);
function getTimestamp(uint _jobId) external view returns (uint);
function getCompanyId(uint _jobId) external view returns (uint);
function getRegId(uint _jobId) external view returns (uint);
function isUnassigned(uint _jobId) external view returns (bool);
function getCapacity(uint _companyId) external view returns (uint);
function ownerOfReg(uint _regId) external view returns (address);
function ownerOf(uint _jobId) external view returns (address);
}
contract FinanceDept is AccessControl, Pausable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint public payDuration = 1 weeks;
uint public maxClaimTime = 10 weeks;
IERC20 regularsToken;
JobsI jobs;
Salaries salaries;
event ClaimedSalary (address wallet, uint amount);
event ClaimedSalaries (address wallet, uint amount);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, tx.origin);
regularsToken = IERC20(0x78b5C6149C87c82EDCffC73C230395abbc56DdD5);
}
function unclaimedDuration(uint _jobId) public view returns (uint) {
uint _duration = block.timestamp - jobs.getTimestamp(_jobId);
return Math.min(_duration, maxClaimTime);
}
function unclaimedByJob(uint _jobId) public view returns (uint) {
return salaries.salary(_jobId) * unclaimedDuration(_jobId) / payDuration;
}
function unclaimedByCompany(uint[] memory _jobIds) public view returns (uint) {
uint _companyId = jobs.getCompanyId(_jobIds[0]);
uint _combinedSalaries = 0;
uint i;
for (i = 0; i < _jobIds.length;i++){
uint _jobId = _jobIds[i];
require(jobs.getCompanyId(_jobId) == _companyId, "Not all same company id");
_combinedSalaries += unclaimedByJob(_jobId);
}
return salaries.teamworkBonus(_combinedSalaries, _jobIds.length, jobs.getCapacity(_companyId));
}
function unclaimedAll(uint[] memory _jobIds) public view returns (uint) {
return 100;
}
function setMaxClaimTime(uint _maxClaimTime) public onlyRole(MINTER_ROLE) {
maxClaimTime = _maxClaimTime;
}
function setPayDuration(uint _payDuration) public onlyRole(MINTER_ROLE) {
payDuration = _payDuration;
}
function pause() public onlyRole(MINTER_ROLE) {
_pause();
}
function unpause() public onlyRole(MINTER_ROLE) {
_unpause();
}
function setJobsByAddr(address _addr) public onlyRole(MINTER_ROLE){
jobs = JobsI(_addr);
}
function setSalariesByAddr(address _addr) public onlyRole(MINTER_ROLE){
salaries = Salaries(_addr);
}
function setRegularsToken(address _addr) public onlyRole(MINTER_ROLE) {
regularsToken = IERC20(_addr);
}
function getRegularsTokenAddress() public view returns (address) {
return address(regularsToken);
}
function getSalariesTokenAddress() public view returns (address) {
return address(salaries);
}
function getJobsTokenAddress() public view returns (address) {
return address(jobs);
}
}
文件 11 的 27:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 12 的 27:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 13 的 27:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 14 的 27:IERC2981.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
interface IERC2981 is IERC165 {
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}
文件 15 的 27:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 16 的 27:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 17 的 27:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 18 的 27:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 19 的 27:JobTransferFunction.sol
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/access/AccessControl.sol";
interface JobsInterface {
function resetJob(uint _jobId) external;
}
contract JobTransferFunction is AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
address jobsAddress;
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, tx.origin);
_grantRole(MINTER_ROLE, msg.sender);
jobsAddress = msg.sender;
}
function jobTransfer(address from, address to, uint256 tokenId) public onlyRole(MINTER_ROLE) {
JobsInterface(jobsAddress).resetJob(tokenId);
}
}
文件 20 的 27:Jobs.sol
pragma solidity ^0.8.12;
import "./JobTransferFunction.sol";
import "./Companies.sol";
import "./Seniority.sol";
import "./Titles.sol";
import "./FinanceDept.sol";
import "./Salaries.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
contract Jobs is ERC721, ERC721Royalty, AccessControl {
using Strings for uint256;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
string private baseURI = "https://jobs.regular.world/cards/id/";
bool public mintOpen = false;
mapping(uint => bool) public minted;
mapping(uint => uint) public timestamps;
mapping(uint => uint) public companyIds;
mapping(uint => uint) public regIds;
mapping(uint => uint) public jobByRegId;
JobTransferFunction jobTransferFunction;
Companies companies;
FinanceDept financeDept;
Salaries salaries;
Seniority seniority;
Titles titles;
ERC721Enumerable regularsNFT;
event Mint(uint jobId, uint indexed companyId, uint regularId);
event Update(uint jobId, uint indexed companyId, uint regularId, string name);
event RegularIdChange (uint256 indexed jobId, uint regId);
event ResetJob (uint256 indexed jobId);
constructor() ERC721("Regular Jobs", "JOBS") {
_setDefaultRoyalty(msg.sender, 500);
regularsNFT = ERC721Enumerable(0x6d0de90CDc47047982238fcF69944555D27Ecb25);
salaries = new Salaries(address(this));
financeDept = new FinanceDept();
jobTransferFunction = new JobTransferFunction();
companies = new Companies();
seniority = new Seniority();
titles = new Titles(address(seniority));
financeDept.setJobsByAddr(address(this));
financeDept.setSalariesByAddr(address(salaries));
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, address(financeDept));
_grantRole(MINTER_ROLE, address(jobTransferFunction));
}
function safeMint(address _to, uint _regId) public {
require(regularsNFT.ownerOf(_regId) == _to, "Not your Regular");
require(!minted[_regId], "Already claimed");
require(mintOpen, "Not minting");
require(!hasJob(_regId),"Reg is working another job");
minted[_regId] = true;
(uint _jobId, uint _companyId) = companies.makeNewJob(_regId);
timestamps[_jobId] = block.timestamp;
companyIds[_jobId] = _companyId;
regIds[_jobId] = _regId;
jobByRegId[_regId] = _jobId;
if (companies.isManager(_regId)){
if (seniority.level(_jobId) == 0)
seniority.setLevel(_jobId,2);
else
seniority.incrementLevel(_jobId);
}
_safeMint(_to, _jobId);
emit Mint(_jobId, _companyId, _regId);
}
function setRegularId(uint _jobId, uint _regId) public {
require(ownerOf(_jobId) == msg.sender, "Not owner of this job.");
require(regularsNFT.ownerOf(_regId) == msg.sender, "Not owner of Regular");
require(regIds[_jobId] != _regId, "This reg already assigned to this job");
require(hasJob(_regId) == false, "This reg already assigned to another job");
uint _prevRegId = regIds[_jobId];
regIds[_jobId] = _regId;
jobByRegId[_prevRegId] = 0;
jobByRegId[_regId] = _jobId;
timestamps[_jobId] = block.timestamp;
emit RegularIdChange(_jobId, _regId);
}
function unassignRegularId(uint _jobId) public {
require(ownerOf(_jobId) == msg.sender, "Not owner of this job.");
uint _oldRegId = regIds[_jobId];
regIds[_jobId] = 10000;
jobByRegId[_oldRegId] = 0;
timestamps[_jobId] = block.timestamp;
emit ResetJob(_jobId);
}
function safeMintMany(address _to, uint[] memory _regIds) public {
for (uint i; i< _regIds.length;i++){
safeMint(_to, _regIds[i]);
}
}
function toggleMinting() public onlyRole(MINTER_ROLE) {
mintOpen = !mintOpen;
}
function setBaseURI(string memory _newPath) public onlyRole(MINTER_ROLE) {
baseURI = _newPath;
}
function resetJob(uint _jobId) public onlyRole(MINTER_ROLE) {
uint _oldRegId = regIds[_jobId];
regIds[_jobId] = 10000;
jobByRegId[_oldRegId] = 0;
timestamps[_jobId] = block.timestamp;
emit ResetJob(_jobId);
}
function setTimestamp(uint _jobId, uint _timestamp) public onlyRole(MINTER_ROLE) {
timestamps[_jobId] = _timestamp;
}
function setCompany(uint _jobId, uint _companyId) external onlyRole(MINTER_ROLE){
companyIds[_jobId] = _companyId;
}
function setRegId(uint _jobId, uint _regId) external onlyRole(MINTER_ROLE){
regIds[_jobId] = _regId;
}
function setJobByRegId(uint _regId, uint _jobId) public onlyRole(MINTER_ROLE) {
jobByRegId[_regId] = _jobId;
}
function sameOwner(uint _jobId) public view returns (bool) {
return ownerOf(_jobId) == ownerOfReg(regIds[_jobId]);
}
function getTimestamp(uint _jobId) public view returns (uint) {
require(_exists(_jobId), "Query for nonexistent token");
return timestamps[_jobId];
}
function getCompanyId(uint _jobId) public view returns (uint) {
require(_exists(_jobId), "Query for nonexistent token");
return companyIds[_jobId];
}
function getRegId(uint _jobId) public view returns (uint) {
require(_exists(_jobId), "Query for nonexistent token");
return regIds[_jobId];
}
function isUnassigned(uint _jobId) public view returns (bool) {
require(_exists(_jobId), "Query for nonexistent token");
return regIds[_jobId] == 10000;
}
function getJobByRegId(uint _regId) public view returns (uint) {
return jobByRegId[_regId];
}
function hasJob(uint _regId) public view returns (bool) {
return jobByRegId[_regId] != 0;
}
function getJobFullDetails(uint _jobId) public view returns (uint, uint, uint, string memory, uint, string memory){
require(_exists(_jobId), "Query for nonexistent token");
uint _salary = salaries.salary(_jobId);
uint _regId = regIds[_jobId];
uint _companyId = companyIds[_jobId];
string memory _companyName = companies.getName(_companyId);
uint _seniority = seniority.level(_jobId);
string memory _title = titles.title(_jobId);
return (_salary, _regId, _companyId, _companyName, _seniority, _title);
}
function getBaseSalary(uint _companyId) public view returns (uint) {
return companies.getBaseSalary(_companyId);
}
function getCompanyName(uint _companyId) public view returns (string memory) {
return companies.getName(_companyId);
}
function getSpread(uint _companyId) public view returns (uint) {
return companies.getSpread(_companyId);
}
function getCapacity(uint _companyId) public view returns (uint) {
return companies.getCapacity(_companyId);
}
function getSalary(uint _jobId) public view returns (uint) {
require(_exists(_jobId), "Query for nonexistent token");
return salaries.salary(_jobId);
}
function getSeniorityLevel(uint _jobId) public view returns (uint) {
return seniority.level(_jobId);
}
function title(uint _jobId) public view returns (string memory) {
require(_exists(_jobId), "Query for nonexistent token");
return titles.title(_jobId);
}
function ownerOfReg(uint _regId) public view returns (address) {
return regularsNFT.ownerOf(_regId);
}
function setContractAddr(string memory _contractName, address _addr) public onlyRole(MINTER_ROLE){
bytes memory _contract = bytes(_contractName);
if (keccak256(_contract) == keccak256(bytes("JobTransferFunction"))) {
jobTransferFunction = JobTransferFunction(_addr);
} else if (keccak256(_contract) == keccak256(bytes("Companies"))) {
companies = Companies(_addr);
} else if (keccak256(_contract) == keccak256(bytes("FinanceDept"))) {
financeDept = FinanceDept(_addr);
} else if (keccak256(_contract) == keccak256(bytes("Seniority"))) {
seniority = Seniority(_addr);
} else if (keccak256(_contract) == keccak256(bytes("Titles"))) {
titles = Titles(_addr);
} else if (keccak256(_contract) == keccak256(bytes("Salaries"))) {
salaries = Salaries(_addr);
} else
revert("No match found");
}
function getContractAddr(string memory _contractName) public view returns (address) {
bytes memory _contract = bytes(_contractName);
if (keccak256(_contract) == keccak256(bytes("JobTransferFunction"))) {
return address(jobTransferFunction);
} else if (keccak256(_contract) == keccak256(bytes("Companies"))) {
return address(companies);
} else if (keccak256(_contract) == keccak256(bytes("FinanceDept"))) {
return address(financeDept);
} else if (keccak256(_contract) == keccak256(bytes("Seniority"))) {
return address(seniority);
} else if (keccak256(_contract) == keccak256(bytes("Titles"))) {
return address(titles);
} else if (keccak256(_contract) == keccak256(bytes("Salaries"))) {
return address(salaries);
} else
revert("None found");
}
function setDefaultRoyalty(address _receiver, uint96 feeNumerator) public onlyRole(MINTER_ROLE){
super._setDefaultRoyalty(_receiver, feeNumerator);
}
function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory) {
require(_exists(tokenId), "Query for nonexistent token");
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721) {
if (from != address(0)){
jobTransferFunction.jobTransfer(from,to,tokenId);
}
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, AccessControl, ERC721Royalty) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721Royalty) {
super._burn(tokenId);
}
function allRegularsByAddress(address _wallet) public view returns(uint[] memory){
uint[] memory nfts = new uint[](regularsNFT.balanceOf(_wallet));
for (uint i = 0; i < nfts.length;i++){
nfts[i] = regularsNFT.tokenOfOwnerByIndex(_wallet, i);
}
return nfts;
}
function unmintedByAddress(address _wallet) public view returns(uint[] memory){
uint unmintedCount = 0;
for (uint i = 0; i < regularsNFT.balanceOf(_wallet);i++){
uint _regId = regularsNFT.tokenOfOwnerByIndex(_wallet, i);
if (!minted[_regId])
unmintedCount++;
}
uint[] memory nfts = new uint[](unmintedCount);
for (uint i = 0; i < nfts.length;i++){
uint _regId = regularsNFT.tokenOfOwnerByIndex(_wallet, i);
if (!minted[_regId])
nfts[i] = _regId;
}
return nfts;
}
}
文件 21 的 27:Math.sol
pragma solidity ^0.8.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b + (a % b == 0 ? 0 : 1);
}
}
文件 22 的 27:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 23 的 27:Random.sol
pragma solidity ^0.8.0;
library Random {
function random() internal view returns (bytes32) {
return keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp, msg.sender)) ;
}
struct Manifest {
uint256[] _data;
}
function setup(Manifest storage self, uint256 length) internal {
uint256[] storage data = self._data;
require(data.length == 0, "cannot-setup-during-active-draw");
assembly { sstore(data.slot, length) }
}
function draw(Manifest storage self) internal returns (uint256) {
return draw(self, random());
}
function draw(Manifest storage self, bytes32 seed) internal returns (uint256) {
uint256[] storage data = self._data;
uint256 l = data.length;
uint256 i = uint256(seed) % l;
uint256 x = data[i];
uint256 y = data[--l];
if (x == 0) { x = i + 1; }
if (y == 0) { y = l + 1; }
if (i != l) { data[i] = y; }
data.pop();
return x - 1;
}
function put(Manifest storage self, uint256 i) internal {
self._data.push(i + 1);
}
function remaining(Manifest storage self) internal view returns (uint256) {
return self._data.length;
}
}
文件 24 的 27:Salaries.sol
pragma solidity ^0.8.12;
import "./Jobs.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
contract Salaries is AccessControl {
uint public constant RANDOM_SEED = 69;
uint public constant SALARY_DECIMALS = 2;
uint public constant MAX_TEAMWORK_BONUS = 300;
uint public SALARY_MULTIPLIER = 100;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
Jobs jobs;
constructor(address _addr) {
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, tx.origin);
jobs = Jobs(_addr);
}
function basepay(uint _jobId, uint _companyBase, uint _companySpread) public view returns (uint) {
uint _baseSalary = _companyBase * 10 ** 18 * SALARY_MULTIPLIER / 100;
uint _spread = _baseSalary * _companySpread / 100;
uint _r = uint(keccak256(abi.encodePacked(_jobId, RANDOM_SEED))) % 100;
uint _result = _baseSalary + (_r * _spread / 100) - (_spread / 2);
return (_result * 4 / 10 ** 20) * 100 / 4 * 10 ** 16;
}
function basepay(uint _jobId) public view returns (uint) {
uint _companyId = jobs.getCompanyId(_jobId);
return basepay(_jobId, companyBase(_companyId), companySpread(_companyId));
}
function seniorityBonus(uint _level, uint _basePay) public pure returns (uint) {
uint _bonusPercent = 0;
if (_level > 0)
_bonusPercent = (2 ** (_level - 1) * 10);
return _bonusPercent * _basePay / 100;
}
function seniorityBonus(uint _jobId) public view returns (uint) {
uint _seniorityLevel = jobs.getSeniorityLevel(_jobId);
uint _basepay = basepay(_jobId);
return seniorityBonus(_seniorityLevel, _basepay);
}
function salary(uint _jobId) public view returns (uint) {
uint _basepay = basepay(_jobId);
uint _seniorityLevel = jobs.getSeniorityLevel(_jobId);
uint _seniorityBonus = seniorityBonus(_seniorityLevel, _basepay);
uint _result = _basepay + _seniorityBonus;
return _result;
}
function teamworkBonus(uint _numOwned, uint _capacity) public pure returns (uint) {
uint _result = 0;
if (_numOwned > 1)
_result = (_numOwned * 100 / _capacity) * 10;
return Math.min(_result,MAX_TEAMWORK_BONUS);
}
function teamworkBonus(uint _totalSalaries, uint _numOwned, uint _capacity) public pure returns (uint) {
return _totalSalaries + (_totalSalaries * teamworkBonus(_numOwned, _capacity) / 100);
}
function teamworkBonus(uint[] memory _jobIds) public view returns (uint) {
uint _companyId = jobs.getCompanyId(_jobIds[0]);
uint _totalSalaries = 0;
for (uint i = 0; i < _jobIds.length;i++){
uint _jobId = _jobIds[i];
require(jobs.getCompanyId(_jobId) == _companyId, "Not all same company id");
_totalSalaries += salary(_jobId);
}
return teamworkBonus(_totalSalaries , _jobIds.length, jobs.getCapacity(_companyId));
}
function companyBase(uint _companyId) public view returns (uint) {
return jobs.getBaseSalary(_companyId);
}
function companySpread(uint _companyId) public view returns (uint) {
return jobs.getSpread(_companyId);
}
function setJobsAddr(address _addr) public onlyRole(MINTER_ROLE) {
jobs = Jobs(_addr);
}
function setSalaryMultiplier(uint _basispoints) public onlyRole(MINTER_ROLE) {
SALARY_MULTIPLIER = _basispoints;
}
}
文件 25 的 27:Seniority.sol
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Seniority is AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint public MAX_LEVELS = 5;
mapping(uint => uint) private levels;
event LevelUpdate (uint _tokenId, uint _newLevel);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, tx.origin);
}
function level(uint _jobID) public view returns (uint) {
return levels[_jobID] + cointoss(_jobID);
}
function incrementLevel(uint _jobID) public onlyRole(MINTER_ROLE) {
require(level(_jobID) < MAX_LEVELS, "At max level");
levels[_jobID] += 1;
emit LevelUpdate(_jobID, level(_jobID));
}
function setLevel(uint _jobID, uint _newLevel) public onlyRole(MINTER_ROLE) {
require(_newLevel <= MAX_LEVELS, "Level too high");
levels[_jobID] = _newLevel;
emit LevelUpdate(_jobID, level(_jobID));
}
function setMaxLevels(uint _newMax) public onlyRole(MINTER_ROLE) {
MAX_LEVELS = _newMax;
}
function cointoss(uint _num) internal pure returns (uint){
return (uint(keccak256(abi.encodePacked(_num))) % 2);
}
}
文件 26 的 27:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 27 的 27:Titles.sol
pragma solidity ^0.8.12;
import "./Seniority.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Titles is AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint public constant MAX_LEVELS = 5;
uint public MAX_CHARS = 28;
mapping(uint => string) private customs;
mapping(uint => bool) public customExists;
Seniority seniority;
event SeniorityUpdate (uint _tokenId, uint _newLevel, string _newPrefix);
event TitleUpdate (uint _tokenId, string _newTitle);
string[] private entryLevelTitles = [
"Asst.",
"Asst. to",
"Jr."
];
string[] private PRE = [
"Entry Level",
"",
"Lead",
"Sr.",
"VP",
"Chief"
];
string[] private A = [
"Office",
"Account",
"Program",
"Project",
"Regional",
"Branch"
];
string[] private B = [
"Department",
"Team",
"Facilities",
"Compliance",
"Mailroom",
"Finance",
"Sales",
"Marketing",
"IT",
"HR",
"Operations",
"Community",
"Business",
"Technical",
"Helpdesk",
"Custodial",
"Data-Entry"
];
string[] private C = [
"Officer",
"Accountant",
"Associate",
"Leader",
"Clerk",
"Administrator",
"Consultant",
"Coordinator",
"Inspector",
"Rep.",
"Support",
"Auditor",
"Specialist",
"Analyst",
"Executive",
"Controller",
"Programmer",
"Developer",
"Support",
"Professional",
"Salesperson",
"Receptionist"
];
constructor(address _addr) {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(DEFAULT_ADMIN_ROLE, tx.origin);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, tx.origin);
seniority = Seniority(_addr);
}
function title(uint _jobID) public view returns (string memory) {
if (customExists[_jobID])
return (customs[_jobID]);
string memory _prefix = titlePrefix(_jobID);
string memory _a;
string memory _b;
string memory _c;
(_a,_b,_c) = titleSeperated(_jobID);
bool _isAssistant = keccak256(abi.encodePacked((_prefix))) == keccak256(abi.encodePacked((entryLevelTitles[0])));
bool _makeSuffix = (_isAssistant && cointoss(_jobID + 10000));
uint _jobLength = bytes(_prefix).length + bytes(_a).length + bytes(_b).length + bytes(_c).length + 3;
if (_jobLength > MAX_CHARS) {
if (cointoss(_jobID)){
if (_makeSuffix)
return myConcat(_b,_c,_prefix,"");
else
return myConcat(_prefix,_b,_c,"");
} else {
if (_makeSuffix)
return myConcat(_a, _c, _prefix, "");
else
return myConcat(_prefix,_a, _c, "");
}
} else {
if (_makeSuffix)
return myConcat(_a, _b, _c, titlePrefix(_jobID));
else
return myConcat(titlePrefix(_jobID),_a, _b, _c);
}
}
function level(uint _jobID) public view returns (uint) {
return seniority.level(_jobID);
}
function setCustomTitle(uint _jobID, string memory _newTitle) public onlyRole(MINTER_ROLE) {
customs[_jobID] = _newTitle;
customExists[_jobID] = true;
emit TitleUpdate(_jobID,_newTitle);
}
function setMaxChars(uint _newMax) public onlyRole(MINTER_ROLE) {
MAX_CHARS = _newMax;
}
function seniorityContractAddress() public view returns (address) {
return address(seniority);
}
function setSeniorityContractAddr(address _addr) public onlyRole(MINTER_ROLE) {
seniority = Seniority(_addr);
}
function titleSeperated(uint _jobID) internal view returns (string memory,string memory,string memory) {
uint _a = uint(keccak256(abi.encodePacked(_jobID))) % A.length;
uint _b = uint(keccak256(abi.encodePacked(_jobID,"abc"))) % B.length;
uint _c = uint(keccak256(abi.encodePacked(_jobID,"def"))) % C.length;
return (A[_a],B[_b],C[_c]);
}
function myConcat(string memory s1, string memory s2, string memory s3, string memory s4) internal pure returns (string memory) {
string memory result;
if (bytes(s1).length > 0)
result = string.concat(s1, " ", s2," ", s3);
else
result = string.concat(s2," ", s3);
if (bytes(s4).length > 0)
result = string.concat(result, " ", s4);
return result;
}
function titlePrefix(uint _jobID) internal view returns (string memory) {
if (level(_jobID) == 0) {
uint _x = uint(keccak256(abi.encodePacked(_jobID))) % entryLevelTitles.length;
return entryLevelTitles[_x];
} else if (level(_jobID) == 1) {
return "";
} else {
return PRE[level(_jobID)];
}
}
function cointoss(uint _num) internal pure returns (bool){
return (uint(keccak256(abi.encodePacked(_num))) % 2 == 0);
}
}
{
"compilationTarget": {
"contracts/Jobs.sol": "Jobs"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"jobId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"companyId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"regularId","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"jobId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"regId","type":"uint256"}],"name":"RegularIdChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"jobId","type":"uint256"}],"name":"ResetJob","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"jobId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"companyId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"regularId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"Update","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"allRegularsByAddress","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"companyIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_companyId","type":"uint256"}],"name":"getBaseSalary","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_companyId","type":"uint256"}],"name":"getCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getCompanyId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_companyId","type":"uint256"}],"name":"getCompanyName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_contractName","type":"string"}],"name":"getContractAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"getJobByRegId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getJobFullDetails","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getRegId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getSalary","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getSeniorityLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_companyId","type":"uint256"}],"name":"getSpread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"getTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"hasJob","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"isUnassigned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"jobByRegId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"ownerOfReg","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"regIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"resetJob","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_regIds","type":"uint256[]"}],"name":"safeMintMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"sameOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newPath","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"},{"internalType":"uint256","name":"_companyId","type":"uint256"}],"name":"setCompany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_contractName","type":"string"},{"internalType":"address","name":"_addr","type":"address"}],"name":"setContractAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_regId","type":"uint256"},{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"setJobByRegId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"},{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"setRegId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"},{"internalType":"uint256","name":"_regId","type":"uint256"}],"name":"setRegularId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"setTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"timestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"title","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_jobId","type":"uint256"}],"name":"unassignRegularId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"unmintedByAddress","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"}]