Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x5992689fBB6dd45EB40848a7021715f4Dea079f7
Balance 0 ETH
Nonce 1
Code Size 9552 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9552 bytes
0x6080604052600436106100fe5760003560e01c80639c8f719a11610095578063ae06c1b711610064578063ae06c1b714610328578063d547741f14610351578063d7c97fb41461037a578063dbcdc2cc146103a5578063f1bab2ec146103ce576100fe565b80639c8f719a1461028b578063a001ecdd146102a7578063a0c76f62146102d2578063a217fddf146102fd576100fe565b806336568abe116100d157806336568abe146101cf57806354fd4d50146101f85780635b7633d01461022357806391d148541461024e576100fe565b806301ffc9a714610103578063046dc16614610140578063248a9ca3146101695780632f2ff15d146101a6575b600080fd5b34801561010f57600080fd5b5061012a600480360381019061012591906115ae565b6103f9565b60405161013791906115f6565b60405180910390f35b34801561014c57600080fd5b506101676004803603810190610162919061166f565b610473565b005b34801561017557600080fd5b50610190600480360381019061018b91906116d2565b6104c5565b60405161019d919061170e565b60405180910390f35b3480156101b257600080fd5b506101cd60048036038101906101c89190611729565b6104e4565b005b3480156101db57600080fd5b506101f660048036038101906101f19190611729565b610506565b005b34801561020457600080fd5b5061020d610581565b60405161021a91906117f9565b60405180910390f35b34801561022f57600080fd5b506102386105ba565b604051610245919061182a565b60405180910390f35b34801561025a57600080fd5b5061027560048036038101906102709190611729565b6105e0565b60405161028291906115f6565b60405180910390f35b6102a560048036038101906102a09190611bf8565b61064a565b005b3480156102b357600080fd5b506102bc610a9a565b6040516102c99190611d15565b60405180910390f35b3480156102de57600080fd5b506102e7610aa0565b6040516102f49190611d8f565b60405180910390f35b34801561030957600080fd5b50610312610ac6565b60405161031f919061170e565b60405180910390f35b34801561033457600080fd5b5061034f600480360381019061034a9190611daa565b610acd565b005b34801561035d57600080fd5b5061037860048036038101906103739190611729565b610ae5565b005b34801561038657600080fd5b5061038f610b07565b60405161039c9190611df8565b60405180910390f35b3480156103b157600080fd5b506103cc60048036038101906103c7919061166f565b610b2d565b005b3480156103da57600080fd5b506103e3610b7f565b6040516103f0919061182a565b60405180910390f35b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061046c575061046b82610ba5565b5b9050919050565b6000801b61048081610c0f565b81600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000806000838152602001908152602001600020600101549050919050565b6104ed826104c5565b6104f681610c0f565b6105008383610c23565b50505050565b61050e610d14565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610572576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61057c8282610d1c565b505050565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6106688888888888886bffffffffffffffffffffffff168888610e0e565b6106728585610f02565b60008867ffffffffffffffff81111561068e5761068d611880565b5b6040519080825280602002602001820160405280156106bc5781602001602082028036833780820191505090505b50905060008967ffffffffffffffff8111156106db576106da611880565b5b60405190808252806020026020018201604052801561070e57816020015b60608152602001906001900390816106f95790505b5090506000805b8a5181101561086f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e798c838151811061076f5761076e611e13565b5b60200260200101516040518263ffffffff1660e01b81526004016107939190611d15565b602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d49190611e6e565b610862578a81815181106107eb576107ea611e13565b5b602002602001015184838151811061080657610805611e13565b5b60200260200101818152505089818151811061082557610824611e13565b5b60200260200101518383815181106108405761083f611e13565b5b6020026020010181905250818061085690611eca565b9250508b82031561086f575b8080600101915050610715565b508a81146108a9576040517f4b0be3a400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663db3e4c8484846040518363ffffffff1660e01b81526004016109069291906120dc565b600060405180830381600087803b15801561092057600080fd5b505af1158015610934573d6000803e3d6000fd5b5050505060005b83518110156109fc57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635944c75385838151811061099557610994611e13565b5b60200260200101518a8a6040518463ffffffff1660e01b81526004016109bd93929190612122565b600060405180830381600087803b1580156109d757600080fd5b505af11580156109eb573d6000803e3d6000fd5b50505050808060010191505061093b565b50600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663de836ebd8d856040518363ffffffff1660e01b8152600401610a5a929190612159565b600060405180830381600087803b158015610a7457600080fd5b505af1158015610a88573d6000803e3d6000fd5b50505050505050505050505050505050565b60025481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000801b81565b6000801b610ada81610c0f565b816002819055505050565b610aee826104c5565b610af781610c0f565b610b018383610d1c565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000801b610b3a81610c0f565b81600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610c2081610c1b610d14565b6111a3565b50565b6000610c2f83836105e0565b610d0957600160008085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610ca6610d14565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610d0e565b600090505b92915050565b600033905090565b6000610d2883836105e0565b15610e0357600080600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610da0610d14565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610e08565b600090505b92915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610ea2610e588a8a8a8a8a8a6111f4565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611262565b73ffffffffffffffffffffffffffffffffffffffff1614610ef8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eef906121fb565b60405180910390fd5b5050505050505050565b81341015610f3c576040517f57130eaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061271060025484610f4f919061221b565b610f59919061228c565b905060008184610f6991906122bd565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1683604051610fb390612322565b60006040518083038185875af1925050503d8060008114610ff0576040519150601f19603f3d011682016040523d82523d6000602084013e610ff5565b606091505b5050905080611030576040517ff0e492a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16848761105591906122bd565b60405161106190612322565b60006040518083038185875af1925050503d806000811461109e576040519150601f19603f3d011682016040523d82523d6000602084013e6110a3565b606091505b50509050806110de576040517f0e89834c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff167f9867ed99c55c23f8a1b27fb1776b6c55ce94330af555b7299d0938aca7680d0d846040516111249190611d15565b60405180910390a2600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167e57d762ad8f1734de771f2b521b2668347c0cee2d709a12254662cd5a7d4180856040516111939190611d15565b60405180910390a2505050505050565b6111ad82826105e0565b6111f05780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016111e7929190612337565b60405180910390fd5b5050565b6000804630898989898989604051602001611216989796959493929190612360565b6040516020818303038152906040528051906020012090508060405160200161123f9190612464565b604051602081830303815290604052805190602001209150509695505050505050565b600080600080611272868661128e565b92509250925061128282826112ea565b82935050505092915050565b600080600060418451036112d35760008060006020870151925060408701519150606087015160001a90506112c58882858561144e565b9550955095505050506112e3565b60006002855160001b9250925092505b9250925092565b600060038111156112fe576112fd61248a565b5b8260038111156113115761131061248a565b5b031561144a576001600381111561132b5761132a61248a565b5b82600381111561133e5761133d61248a565b5b03611375576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156113895761138861248a565b5b82600381111561139c5761139b61248a565b5b036113e1578060001c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016113d89190611d15565b60405180910390fd5b6003808111156113f4576113f361248a565b5b8260038111156114075761140661248a565b5b0361144957806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401611440919061170e565b60405180910390fd5b5b5050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c111561148e576000600385925092509250611538565b6000600188888888604051600081526020016040526040516114b394939291906124d5565b6020604051602081039080840390855afa1580156114d5573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361152957600060016000801b93509350935050611538565b8060008060001b935093509350505b9450945094915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61158b81611556565b811461159657600080fd5b50565b6000813590506115a881611582565b92915050565b6000602082840312156115c4576115c361154c565b5b60006115d284828501611599565b91505092915050565b60008115159050919050565b6115f0816115db565b82525050565b600060208201905061160b60008301846115e7565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061163c82611611565b9050919050565b61164c81611631565b811461165757600080fd5b50565b60008135905061166981611643565b92915050565b6000602082840312156116855761168461154c565b5b60006116938482850161165a565b91505092915050565b6000819050919050565b6116af8161169c565b81146116ba57600080fd5b50565b6000813590506116cc816116a6565b92915050565b6000602082840312156116e8576116e761154c565b5b60006116f6848285016116bd565b91505092915050565b6117088161169c565b82525050565b600060208201905061172360008301846116ff565b92915050565b600080604083850312156117405761173f61154c565b5b600061174e858286016116bd565b925050602061175f8582860161165a565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156117a3578082015181840152602081019050611788565b60008484015250505050565b6000601f19601f8301169050919050565b60006117cb82611769565b6117d58185611774565b93506117e5818560208601611785565b6117ee816117af565b840191505092915050565b6000602082019050818103600083015261181381846117c0565b905092915050565b61182481611631565b82525050565b600060208201905061183f600083018461181b565b92915050565b6000819050919050565b61185881611845565b811461186357600080fd5b50565b6000813590506118758161184f565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6118b8826117af565b810181811067ffffffffffffffff821117156118d7576118d6611880565b5b80604052505050565b60006118ea611542565b90506118f682826118af565b919050565b600067ffffffffffffffff82111561191657611915611880565b5b602082029050602081019050919050565b600080fd5b600061193f61193a846118fb565b6118e0565b9050808382526020820190506020840283018581111561196257611961611927565b5b835b8181101561198b57806119778882611866565b845260208401935050602081019050611964565b5050509392505050565b600082601f8301126119aa576119a961187b565b5b81356119ba84826020860161192c565b91505092915050565b600067ffffffffffffffff8211156119de576119dd611880565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff821115611a0f57611a0e611880565b5b611a18826117af565b9050602081019050919050565b82818337600083830152505050565b6000611a47611a42846119f4565b6118e0565b905082815260208101848484011115611a6357611a626119ef565b5b611a6e848285611a25565b509392505050565b600082601f830112611a8b57611a8a61187b565b5b8135611a9b848260208601611a34565b91505092915050565b6000611ab7611ab2846119c3565b6118e0565b90508083825260208201905060208402830185811115611ada57611ad9611927565b5b835b81811015611b2157803567ffffffffffffffff811115611aff57611afe61187b565b5b808601611b0c8982611a76565b85526020850194505050602081019050611adc565b5050509392505050565b600082601f830112611b4057611b3f61187b565b5b8135611b50848260208601611aa4565b91505092915050565b60006bffffffffffffffffffffffff82169050919050565b611b7a81611b59565b8114611b8557600080fd5b50565b600081359050611b9781611b71565b92915050565b600080fd5b60008083601f840112611bb857611bb761187b565b5b8235905067ffffffffffffffff811115611bd557611bd4611b9d565b5b602083019150836001820283011115611bf157611bf0611927565b5b9250929050565b60008060008060008060008060006101008a8c031215611c1b57611c1a61154c565b5b6000611c298c828d0161165a565b9950506020611c3a8c828d01611866565b98505060408a013567ffffffffffffffff811115611c5b57611c5a611551565b5b611c678c828d01611995565b97505060608a013567ffffffffffffffff811115611c8857611c87611551565b5b611c948c828d01611b2b565b9650506080611ca58c828d01611866565b95505060a0611cb68c828d0161165a565b94505060c0611cc78c828d01611b88565b93505060e08a013567ffffffffffffffff811115611ce857611ce7611551565b5b611cf48c828d01611ba2565b92509250509295985092959850929598565b611d0f81611845565b82525050565b6000602082019050611d2a6000830184611d06565b92915050565b6000819050919050565b6000611d55611d50611d4b84611611565b611d30565b611611565b9050919050565b6000611d6782611d3a565b9050919050565b6000611d7982611d5c565b9050919050565b611d8981611d6e565b82525050565b6000602082019050611da46000830184611d80565b92915050565b600060208284031215611dc057611dbf61154c565b5b6000611dce84828501611866565b91505092915050565b6000611de282611d5c565b9050919050565b611df281611dd7565b82525050565b6000602082019050611e0d6000830184611de9565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b611e4b816115db565b8114611e5657600080fd5b50565b600081519050611e6881611e42565b92915050565b600060208284031215611e8457611e8361154c565b5b6000611e9284828501611e59565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611ed582611845565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f0757611f06611e9b565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611f4781611845565b82525050565b6000611f598383611f3e565b60208301905092915050565b6000602082019050919050565b6000611f7d82611f12565b611f878185611f1d565b9350611f9283611f2e565b8060005b83811015611fc3578151611faa8882611f4d565b9750611fb583611f65565b925050600181019050611f96565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061201882611769565b6120228185611ffc565b9350612032818560208601611785565b61203b816117af565b840191505092915050565b6000612052838361200d565b905092915050565b6000602082019050919050565b600061207282611fd0565b61207c8185611fdb565b93508360208202850161208e85611fec565b8060005b858110156120ca57848403895281516120ab8582612046565b94506120b68361205a565b925060208a01995050600181019050612092565b50829750879550505050505092915050565b600060408201905081810360008301526120f68185611f72565b9050818103602083015261210a8184612067565b90509392505050565b61211c81611b59565b82525050565b60006060820190506121376000830186611d06565b612144602083018561181b565b6121516040830184612113565b949350505050565b600060408201905061216e600083018561181b565b81810360208301526121808184611f72565b90509392505050565b7f5369676e617475726550726f7465637465643a20496e76616c6964207369676e60008201527f617475726520666f72207468652063616c6c6572000000000000000000000000602082015250565b60006121e5603483611774565b91506121f082612189565b604082019050919050565b60006020820190508181036000830152612214816121d8565b9050919050565b600061222682611845565b915061223183611845565b925082820261223f81611845565b9150828204841483151761225657612255611e9b565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061229782611845565b91506122a283611845565b9250826122b2576122b161225d565b5b828204905092915050565b60006122c882611845565b91506122d383611845565b92508282039050818111156122eb576122ea611e9b565b5b92915050565b600081905092915050565b50565b600061230c6000836122f1565b9150612317826122fc565b600082019050919050565b600061232d826122ff565b9150819050919050565b600060408201905061234c600083018561181b565b61235960208301846116ff565b9392505050565b600061010082019050612376600083018b611d06565b612383602083018a61181b565b6123906040830189611d06565b81810360608301526123a28188611f72565b905081810360808301526123b68187612067565b90506123c560a0830186611d06565b6123d260c083018561181b565b6123df60e0830184611d06565b9998505050505050505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061242d601c836123ec565b9150612438826123f7565b601c82019050919050565b6000819050919050565b61245e6124598261169c565b612443565b82525050565b600061246f82612420565b915061247b828461244d565b60208201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060ff82169050919050565b6124cf816124b9565b82525050565b60006080820190506124ea60008301876116ff565b6124f760208301866124c6565b61250460408301856116ff565b61251160608301846116ff565b9594505050505056fea2646970667358221220afdd293dafbee5d5895d6581faf271200cf072b1baf108dcd0a6f36565a7bfa464736f6c634300081c0033

Verified Source Code Full Match

Compiler: v0.8.28+commit.7893614a EVM: paris Optimization: No
AccessControl.sol 209 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
IAccessControl.sol 98 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
ECDSA.sol 180 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(
        bytes32 hash,
        bytes memory signature
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly ("memory-safe") {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}
ERC165.sol 27 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
Minter.sol 69 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IERC721Mintable} from './interfaces/IERC721Mintable.sol';
import {IMetadataResolver} from './interfaces/IMetadataResolver.sol';
import {Payable} from './libs/Payable.sol';
import {SignatureProtected} from './libs/SignatureProtected.sol';

contract WiseMinter is Payable, SignatureProtected {
  error NotEnoughTokensLeftToMint();

  string public constant version = '1.0.0';

  IERC721Mintable public erc721Contract;
  IMetadataResolver public metadataResolver;

  constructor(
    address _erc721Address,
    address _metadataResolver,
    address _feeRecipient,
    address _signerAddress
  ) Payable(_feeRecipient) SignatureProtected(_signerAddress) {
    erc721Contract = IERC721Mintable(_erc721Address);
    metadataResolver = IMetadataResolver(_metadataResolver);
  }

  function mint(
    address _recipient,
    uint256 _amount,
    uint256[] memory _ids,
    string[] memory _tokenURIs,
    uint256 _totalPrice,
    address _artistAddress,
    uint96 _royalty,
    bytes calldata _signature
  ) external payable {
    validateSignature(_amount, _ids, _tokenURIs, _totalPrice, _artistAddress, _royalty, _signature);
    handlePayment(_totalPrice, _artistAddress);

    uint256[] memory ids = new uint256[](_amount);
    string[] memory tokenURIs = new string[](_amount);

    uint256 found = 0;
    for (uint256 i; i < _ids.length; i++) {
      if (erc721Contract.exists(_ids[i])) {
        continue;
      }

      ids[found] = _ids[i];
      tokenURIs[found] = _tokenURIs[i];

      found++;

      if (found == _amount) {
        break;
      }
    }

    if (found != _amount) revert NotEnoughTokensLeftToMint();

    metadataResolver.setTokenURIs(ids, tokenURIs);

    for (uint256 i; i < ids.length; i++) {
      erc721Contract.setTokenRoyalty(ids[i], _artistAddress, _royalty);
    }

    erc721Contract.mint(_recipient, ids);
  }
}
IERC721Mintable.sol 10 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

interface IERC721Mintable {
  function mint(address _to, uint256[] memory _ids) external;

  function setTokenRoyalty(uint256 _tokenId, address _receiver, uint96 _feeNumerator) external;

  function exists(uint256 tokenId) external view returns (bool);
}
IMetadataResolver.sol 8 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

interface IMetadataResolver {
  function getTokenURI(uint256 _tokenId) external view returns (string memory);

  function setTokenURIs(uint256[] memory _tokenIds, string[] memory _uris) external;
}
Payable.sol 48 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {AccessControl} from '@openzeppelin/contracts/access/AccessControl.sol';

abstract contract Payable is AccessControl {
  error FeePaymentFailed();
  error ArtistPaymentFailed();

  event ArtistPayment(address indexed recipient, uint256 amount);
  event FeePayment(address indexed recipient, uint256 amount);
  error PaymentInsufficient();

  uint256 constant BASIS_POINTS = 10_000;
  address public feeRecipientAddress;
  uint256 public feePercentage = 1_000;

  constructor(address _feeRecipientAddress) {
    _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    feeRecipientAddress = _feeRecipientAddress;
  }

  function setFeeRecipientAddress(
    address _feeRecipientAddress
  ) external onlyRole(DEFAULT_ADMIN_ROLE) {
    feeRecipientAddress = _feeRecipientAddress;
  }

  function setFeePercentage(uint256 _feePercentage) external onlyRole(DEFAULT_ADMIN_ROLE) {
    feePercentage = _feePercentage;
  }

  function handlePayment(uint256 _totalPrice, address _artistAddress) internal {
    if (msg.value < _totalPrice) revert PaymentInsufficient();

    uint256 feeAmount = (_totalPrice * feePercentage) / BASIS_POINTS;
    uint256 artistAmount = _totalPrice - feeAmount;

    (bool feeSuccess, ) = feeRecipientAddress.call{value: feeAmount}('');
    if (!feeSuccess) revert FeePaymentFailed();

    (bool artistSuccess, ) = _artistAddress.call{value: _totalPrice - feeAmount}('');
    if (!artistSuccess) revert ArtistPaymentFailed();

    emit ArtistPayment(_artistAddress, artistAmount);
    emit FeePayment(feeRecipientAddress, feeAmount);
  }
}
SignatureProtected.sol 62 lines
// SPDX-License-Identifier: MIT
// @author: Buildtree - Powered by NFT Studios

pragma solidity ^0.8.18;

import {ECDSA} from '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import {AccessControl} from '@openzeppelin/contracts/access/AccessControl.sol';

abstract contract SignatureProtected is AccessControl {
  address public signerAddress;

  constructor(address _signerAddress) {
    _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    signerAddress = _signerAddress;
  }

  function setSignerAddress(address _signerAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
    signerAddress = _signerAddress;
  }

  function validateSignature(
    uint256 _amount,
    uint256[] memory _ids,
    string[] memory _tokenURIs,
    uint256 _totalPrice,
    address _artistAddress,
    uint256 _royalty,
    bytes calldata _signature
  ) internal view {
    require(
      ECDSA.recover(
        generateHash(_amount, _ids, _tokenURIs, _totalPrice, _artistAddress, _royalty),
        _signature
      ) == signerAddress,
      'SignatureProtected: Invalid signature for the caller'
    );
  }

  function generateHash(
    uint256 _amount,
    uint256[] memory _ids,
    string[] memory _tokenURIs,
    uint256 _totalPrice,
    address _artistAddress,
    uint256 _royalty
  ) private view returns (bytes32) {
    bytes32 messageHash = keccak256(
      abi.encode(
        block.chainid,
        address(this),
        _amount,
        _ids,
        _tokenURIs,
        _totalPrice,
        _artistAddress,
        _royalty
      )
    );

    return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', messageHash));
  }
}

Read Contract

DEFAULT_ADMIN_ROLE 0xa217fddf → bytes32
erc721Contract 0xd7c97fb4 → address
feePercentage 0xa001ecdd → uint256
feeRecipientAddress 0xf1bab2ec → address
getRoleAdmin 0x248a9ca3 → bytes32
hasRole 0x91d14854 → bool
metadataResolver 0xa0c76f62 → address
signerAddress 0x5b7633d0 → address
supportsInterface 0x01ffc9a7 → bool
version 0x54fd4d50 → string

Write Contract 7 functions

These functions modify contract state and require a wallet transaction to execute.

grantRole 0x2f2ff15d
bytes32 role
address account
mint 0x9c8f719a
address _recipient
uint256 _amount
uint256[] _ids
string[] _tokenURIs
uint256 _totalPrice
address _artistAddress
uint96 _royalty
bytes _signature
renounceRole 0x36568abe
bytes32 role
address callerConfirmation
revokeRole 0xd547741f
bytes32 role
address account
setFeePercentage 0xae06c1b7
uint256 _feePercentage
setFeeRecipientAddress 0xdbcdc2cc
address _feeRecipientAddress
setSignerAddress 0x046dc166
address _signerAddress

Recent Transactions

No transactions found for this address