Overview
ETH Balance
More Info
ContractCreator
Multichain Info
Latest 25 from a total of 73 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint | 10969955 | 489 days ago | IN | 0.005 ETH | 0.00000029 | ||||
| Mint | 10969224 | 489 days ago | IN | 0.04 ETH | 0.00000029 | ||||
| Mint | 10969177 | 489 days ago | IN | 0.005 ETH | 0.00000028 | ||||
| Mint | 10969144 | 489 days ago | IN | 0.005 ETH | 0.00000029 | ||||
| Mint | 10966462 | 489 days ago | IN | 0.005 ETH | 0.00000029 | ||||
| Mint | 10966420 | 489 days ago | IN | 0.005 ETH | 0.00000028 | ||||
| Mint | 10966385 | 489 days ago | IN | 0.005 ETH | 0.00000028 | ||||
| Mint | 10941684 | 490 days ago | IN | 0.01 ETH | 0.00021794 | ||||
| Mint | 10941661 | 490 days ago | IN | 0.005 ETH | 0.00023571 | ||||
| Mint | 10940756 | 490 days ago | IN | 0.015 ETH | 0.00003491 | ||||
| Mint | 10940667 | 490 days ago | IN | 0.005 ETH | 0.00002589 | ||||
| Mint | 10937945 | 490 days ago | IN | 0.05 ETH | 0.00003256 | ||||
| Mint | 10937920 | 490 days ago | IN | 0.025 ETH | 0.00003655 | ||||
| Mint | 10937804 | 490 days ago | IN | 0.005 ETH | 0.00003137 | ||||
| Mint | 10936807 | 490 days ago | IN | 0.05 ETH | 0.00002743 | ||||
| Mint | 10936736 | 490 days ago | IN | 0.05 ETH | 0.00002448 | ||||
| Mint | 10936198 | 490 days ago | IN | 0.0001 ETH | 0.00002431 | ||||
| Mint | 10935922 | 490 days ago | IN | 0.005 ETH | 0.00002541 | ||||
| Mint | 10935893 | 490 days ago | IN | 0.01 ETH | 0.00002968 | ||||
| Mint | 10935304 | 490 days ago | IN | 0.01 ETH | 0.00002635 | ||||
| Mint | 10935089 | 490 days ago | IN | 0.02 ETH | 0.00002264 | ||||
| Mint | 10935060 | 490 days ago | IN | 0.005 ETH | 0.00002655 | ||||
| Mint | 10934903 | 490 days ago | IN | 0.0003 ETH | 0.00002348 | ||||
| Mint | 10934670 | 490 days ago | IN | 0.0001 ETH | 0.00002718 | ||||
| Mint | 10934545 | 490 days ago | IN | 0.005 ETH | 0.00002866 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | Amount | ||
|---|---|---|---|---|---|---|
| 10969955 | 489 days ago | 0.00001 ETH | ||||
| 10969224 | 489 days ago | 0.00001 ETH | ||||
| 10969177 | 489 days ago | 0.00001 ETH | ||||
| 10969144 | 489 days ago | 0.00001 ETH | ||||
| 10966462 | 489 days ago | 0.00001 ETH | ||||
| 10966420 | 489 days ago | 0.00001 ETH | ||||
| 10966385 | 489 days ago | 0.00001 ETH | ||||
| 10941684 | 490 days ago | 0.00001 ETH | ||||
| 10941661 | 490 days ago | 0.00001 ETH | ||||
| 10940756 | 490 days ago | 0.00001 ETH | ||||
| 10940667 | 490 days ago | 0.00001 ETH | ||||
| 10937945 | 490 days ago | 0.00001 ETH | ||||
| 10937920 | 490 days ago | 0.00001 ETH | ||||
| 10937804 | 490 days ago | 0.00001 ETH | ||||
| 10936807 | 490 days ago | 0.00001 ETH | ||||
| 10936736 | 490 days ago | 0.00001 ETH | ||||
| 10936198 | 490 days ago | 0.00001 ETH | ||||
| 10935922 | 490 days ago | 0.00001 ETH | ||||
| 10935893 | 490 days ago | 0.00001 ETH | ||||
| 10935304 | 490 days ago | 0.00001 ETH | ||||
| 10935089 | 490 days ago | 0.00001 ETH | ||||
| 10935060 | 490 days ago | 0.00001 ETH | ||||
| 10934903 | 490 days ago | 0.00001 ETH | ||||
| 10934670 | 490 days ago | 0.00001 ETH | ||||
| 10934545 | 490 days ago | 0.00001 ETH |
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;
import {IEntropyConsumer} from '@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol';
import {IEntropy} from '@pythnetwork/entropy-sdk-solidity/IEntropy.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import './libs/SignerLib.sol';
import './Gangster.sol';
import './interfaces/IBlast.sol';
contract Minter is Ownable, IEntropyConsumer {
using SignerLib for address;
struct Phase {
uint32 MAX_PER_BATCH;
uint256 BASE_PRICE;
bool status;
bool whitelistedOnly;
uint32 MIN_VALUE;
uint32 MAX_VALUE;
}
struct MintInfo {
address addr;
uint16 amount;
uint256[] values;
bytes32 randomNumber;
uint256 phaseId;
}
struct Probability {
uint probability;
uint gangsterReward;
uint MAX_PROBAILITY;
}
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
address private gasFeeOperator;
IEntropy entropy = IEntropy(0x98046Bd286715D3B0BC227Dd7a956b83D8978603);
address public provider;
Gangster gangster;
address private signer; // Signer address
address private worker; // Worker address
address private treasuryAddr; // Treasury address
mapping(uint256 => Phase) public mintPhase; // phaseId => phase info
mapping(uint64 => MintInfo) public mintData; // Pyth sequense number => MintInfo
mapping(bytes32 => uint64) public requestedRandomNumber; // userRequestRandom => Pyth sequense number
Probability[] public probabilities;
/**
***************************
*Public
***************************
*/
event RequestMint(address addr, uint256 amount, uint256 phaseId, uint64 sequenceNumber);
event RevealMint(address addr, uint256 amount, uint256 phaseId, uint64 sequenceNumber);
event EntropyResult(address entropy, uint64 sequence, address provider, bytes32 randomNumber);
constructor(address initialOwner, address _gangster, address _signer) Ownable(initialOwner) {
gangster = Gangster(_gangster);
signer = _signer;
BLAST.configureClaimableGas();
}
receive() external payable {}
fallback() external payable {}
/**
***************************
Public
***************************
*/
/**
* Claim gas
*/
function claimGas(bool _maxOnly) public {
require(gasFeeOperator != address(0), 'gasFee is not set');
if (_maxOnly) {
BLAST.claimMaxGas(address(this), gasFeeOperator);
} else {
BLAST.claimAllGas(address(this), gasFeeOperator);
}
}
/**
* @notice mint
* phaseId: Id of phase, which contains information of minting
* amount: number of nfts
* sig: signatire from application
*/
function mint(uint256 phaseId_, uint16 amount_, bytes32 userRandomNumber_, bytes memory sig_) public payable {
require(mintPhase[phaseId_].status, 'Mint phase is not available'); // check phase status
require(mintPhase[phaseId_].MAX_PER_BATCH >= amount_, 'Over max per batch'); // Limit max per batch
require(requestedRandomNumber[userRandomNumber_] == 0, 'Rad is used');
uint256 mintFee = amount_ * mintPhase[phaseId_].BASE_PRICE;
uint pythFee = entropy.getFee(provider);
uint totalFee = pythFee + mintFee;
if (mintPhase[phaseId_].BASE_PRICE > 0) {
require(msg.value >= totalFee, 'Send more eth');
}
if (mintPhase[phaseId_].whitelistedOnly) {
bytes32 message = SignerLib.prefixed(
keccak256(abi.encodePacked(msg.sender, phaseId_, amount_, userRandomNumber_))
);
require(signer.verifyAddressSigner(message, sig_), 'Invalid signature'); // validate signature
}
// pay the fees and request a random number from entropy
uint64 sequenceNumber = entropy.requestWithCallback{value: pythFee}(provider, userRandomNumber_);
requestedRandomNumber[userRandomNumber_] = sequenceNumber;
mintData[sequenceNumber].addr = msg.sender;
mintData[sequenceNumber].amount = amount_;
mintData[sequenceNumber].phaseId = phaseId_;
emit RequestMint(msg.sender, amount_, phaseId_, sequenceNumber);
}
// ============================== VIEW FUNCTION ==============================
// This method is required by the IEntropyConsumer interface
function getEntropy() internal view override returns (address) {
return address(entropy);
}
// Get the fee to flip a coin. See the comment above about fees.
function getFee() public view returns (uint256 fee) {
fee = entropy.getFee(provider);
}
function getMintValues(uint64 sequence) public view returns (uint[] memory) {
return mintData[sequence].values;
}
/**
***************************
DEFAULT_ADMIN_ROLE Function
***************************
*/
/**
* @notice withdraw
* withdraw to treasuryAddr_
*/
function withdraw() public onlyOwner {
require(address(this).balance > 0, 'Nothing to withdraw');
require(treasuryAddr != address(0), 'Treasury is not set');
address payable receiver = payable(treasuryAddr);
receiver.transfer(address(this).balance);
}
/**
* @notice emegencyWithdraw
* withdraw to owner address
*/
function emegencyWithdraw() public onlyOwner {
require(address(this).balance > 0, 'Nothing to withdraw');
address payable receiver = payable(msg.sender);
receiver.transfer(address(this).balance);
}
/**
* @dev Update Pyth address
*/
function updatePyth(address _entropy, address _provider) external onlyOwner {
require(_entropy != address(0), 'NOT_ALLOWED_ZERO_ADDRESS');
require(_provider != address(0), 'NOT_ALLOWED_ZERO_ADDRESS');
entropy = IEntropy(_entropy);
provider = _provider;
}
/**
* set GasFeeOperator
*/
function setGasFeeOperator(address _gasFeeOperator) public onlyOwner {
gasFeeOperator = _gasFeeOperator;
}
function setTreasuryAddress(address _addr) public onlyOwner {
treasuryAddr = _addr; // Max supply for presale
}
function setWorker(address _addr) public onlyOwner {
worker = _addr; // Max supply for presale
}
function updatePhase(
uint256 _phaseId,
uint32 _maxPerBatch,
uint256 _basePrice,
bool _status,
bool _whitelistedOnly
) public onlyOwner {
mintPhase[_phaseId].MAX_PER_BATCH = _maxPerBatch;
mintPhase[_phaseId].BASE_PRICE = _basePrice;
mintPhase[_phaseId].status = _status;
mintPhase[_phaseId].whitelistedOnly = _whitelistedOnly;
}
function updateProbability(uint256[] memory _probability, uint256[] memory _gangsterReward) public onlyOwner {
require(sumOf(_probability) == 1000, 'Invalid input');
// probabilities = new Probability[](_probability.length);
for (uint256 i = 0; i < _probability.length; i++) {
probabilities.push(Probability(_probability[i], _gangsterReward[i], 1000));
}
}
function entropyCallback(uint64 _sequence, address _provider, bytes32 _randomNumber) internal override {
emit EntropyResult(msg.sender, _sequence, provider, _randomNumber);
require(_msgSender() == address(entropy) && provider == _provider, 'Caller is not entropy');
MintInfo storage mintInfo = mintData[_sequence];
address playerAddress = mintInfo.addr;
uint16 amount = mintInfo.amount;
uint256 total = 0;
require(uint(mintInfo.randomNumber) == 0, 'Mint is revealed');
mintInfo.randomNumber = _randomNumber;
uint256[] memory arr = _calculateMintResult(uint256(_randomNumber), amount);
total = sumOf(arr);
mintInfo.values = arr;
gangster.mint(playerAddress, 1, total, '');
emit RevealMint(playerAddress, total, 1, _sequence);
}
function manualCallback(uint64 _sequence, bytes32 _randomNumber) public {
emit EntropyResult(msg.sender, _sequence, provider, _randomNumber);
require(_msgSender() == worker, 'Caller is not worker');
MintInfo storage mintInfo = mintData[_sequence];
address playerAddress = mintInfo.addr;
uint16 amount = mintInfo.amount;
uint256 total = 0;
require(uint(mintInfo.randomNumber) == 0, 'Mint is revealed');
mintInfo.randomNumber = _randomNumber;
uint256[] memory arr = _calculateMintResult(uint256(_randomNumber), amount);
total = sumOf(arr);
mintInfo.values = arr;
gangster.mint(playerAddress, 1, total, '');
emit RevealMint(playerAddress, total, 1, _sequence);
}
function _calculateMintResult(uint256 randomNumber, uint256 amount) public view returns (uint256[] memory) {
uint256[] memory arr = new uint256[](amount);
for (uint16 i = 0; i < amount; i++) {
uint256 rad = uint256((randomNumber / (1000 ** i)) % 1000);
arr[i] = _calculateProbability(rad);
}
return arr;
}
function _calculateProbability(uint256 randomNumber) public view returns (uint256) {
uint256 currentProbability = 0;
for (uint256 i = 0; i < probabilities.length; i++) {
currentProbability += probabilities[i].probability;
if (randomNumber < currentProbability) return probabilities[i].gangsterReward;
}
return 0;
}
/**
* @notice sum of array
*/
function sumOf(uint[] memory arr) internal pure returns (uint256 result) {
for (uint256 i = 0; i < arr.length; i++) {
result += arr[i];
}
return result;
}
}// 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;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 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, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
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;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.20;
import {IERC1155} from "./IERC1155.sol";
import {IERC1155Receiver} from "./IERC1155Receiver.sol";
import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol";
import {Context} from "../../utils/Context.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {Arrays} from "../../utils/Arrays.sol";
import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
*/
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
using Arrays for uint256[];
using Arrays for address[];
mapping(uint256 id => mapping(address account => uint256)) private _balances;
mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
string private _uri;
/**
* @dev See {_setURI}.
*/
constructor(string memory uri_) {
_setURI(uri_);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC1155MetadataURI-uri}.
*
* This implementation returns the same URI for *all* token types. It relies
* on the token type ID substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/
function uri(uint256 /* id */) public view virtual returns (string memory) {
return _uri;
}
/**
* @dev See {IERC1155-balanceOf}.
*/
function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
return _balances[id][account];
}
/**
* @dev See {IERC1155-balanceOfBatch}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view virtual returns (uint256[] memory) {
if (accounts.length != ids.length) {
revert ERC1155InvalidArrayLength(ids.length, accounts.length);
}
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
}
return batchBalances;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
return _operatorApprovals[account][operator];
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeTransferFrom(from, to, id, value, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeBatchTransferFrom(from, to, ids, values, data);
}
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from`
* (or `to`) is the zero address.
*
* Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received}
* or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value.
* - `ids` and `values` must have the same length.
*
* NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead.
*/
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
if (ids.length != values.length) {
revert ERC1155InvalidArrayLength(ids.length, values.length);
}
address operator = _msgSender();
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids.unsafeMemoryAccess(i);
uint256 value = values.unsafeMemoryAccess(i);
if (from != address(0)) {
uint256 fromBalance = _balances[id][from];
if (fromBalance < value) {
revert ERC1155InsufficientBalance(from, fromBalance, value, id);
}
unchecked {
// Overflow not possible: value <= fromBalance
_balances[id][from] = fromBalance - value;
}
}
if (to != address(0)) {
_balances[id][to] += value;
}
}
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
emit TransferSingle(operator, from, to, id, value);
} else {
emit TransferBatch(operator, from, to, ids, values);
}
}
/**
* @dev Version of {_update} that performs the token acceptance check by calling
* {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it
* contains code (eg. is a smart contract at the moment of execution).
*
* IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any
* update to the contract state after this function would break the check-effect-interaction pattern. Consider
* overriding {_update} instead.
*/
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal virtual {
_update(from, to, ids, values);
if (to != address(0)) {
address operator = _msgSender();
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
_doSafeTransferAcceptanceCheck(operator, from, to, id, value, data);
} else {
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data);
}
}
}
/**
* @dev Transfers a `value` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
* - `ids` and `values` must have the same length.
*/
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, to, ids, values, data);
}
/**
* @dev Sets a new URI for all token types, by relying on the token type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* By this mechanism, any occurrence of the `\{id\}` substring in either the
* URI or any of the values in the JSON file at said URI will be replaced by
* clients with the token type ID.
*
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
* interpreted by clients as
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
* for token type ID 0x4cce0.
*
* See {uri}.
*
* Because these URIs cannot be meaningfully represented by the {URI} event,
* this function emits no events.
*/
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
/**
* @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
_updateWithAcceptanceCheck(address(0), to, ids, values, data);
}
/**
* @dev Destroys a `value` amount of tokens of type `id` from `from`
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `value` amount of tokens of type `id`.
*/
function _burn(address from, uint256 id, uint256 value) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `value` amount of tokens of type `id`.
* - `ids` and `values` must have the same length.
*/
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, address(0), ids, values, "");
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the zero address.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC1155InvalidOperator(address(0));
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address
* if it contains code at the moment of execution.
*/
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 value,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
// Tokens rejected
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-ERC1155Receiver implementer
revert ERC1155InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
/**
* @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address
* if it contains code at the moment of execution.
*/
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) private {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
// Tokens rejected
revert ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-ERC1155Receiver implementer
revert ERC1155InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
/**
* @dev Creates an array in memory with only one value for each of the elements provided.
*/
function _asSingletonArrays(
uint256 element1,
uint256 element2
) private pure returns (uint256[] memory array1, uint256[] memory array2) {
/// @solidity memory-safe-assembly
assembly {
// Load the free memory pointer
array1 := mload(0x40)
// Set array length to 1
mstore(array1, 1)
// Store the single element at the next word after the length (where content starts)
mstore(add(array1, 0x20), element1)
// Repeat for next array locating it right after the first array
array2 := add(array1, 0x40)
mstore(array2, 1)
mstore(add(array2, 0x20), element2)
// Update the free memory pointer by pointing after the second array
mstore(0x40, add(array2, 0x40))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol)
pragma solidity ^0.8.20;
import {ERC1155} from "../ERC1155.sol";
/**
* @dev Extension of {ERC1155} that allows token holders to destroy both their
* own tokens and those that they have been approved to use.
*/
abstract contract ERC1155Burnable is ERC1155 {
function burn(address account, uint256 id, uint256 value) public virtual {
if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) {
revert ERC1155MissingApprovalForAll(_msgSender(), account);
}
_burn(account, id, value);
}
function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual {
if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) {
revert ERC1155MissingApprovalForAll(_msgSender(), account);
}
_burnBatch(account, ids, values);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Supply.sol)
pragma solidity ^0.8.20;
import {ERC1155} from "../ERC1155.sol";
/**
* @dev Extension of ERC1155 that adds tracking of total supply per id.
*
* Useful for scenarios where Fungible and Non-fungible tokens have to be
* clearly identified. Note: While a totalSupply of 1 might mean the
* corresponding is an NFT, there is no guarantees that no other token with the
* same id are not going to be minted.
*
* NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens
* that can be minted.
*
* CAUTION: This extension should not be added in an upgrade to an already deployed contract.
*/
abstract contract ERC1155Supply is ERC1155 {
mapping(uint256 id => uint256) private _totalSupply;
uint256 private _totalSupplyAll;
/**
* @dev Total value of tokens in with a given id.
*/
function totalSupply(uint256 id) public view virtual returns (uint256) {
return _totalSupply[id];
}
/**
* @dev Total value of tokens.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupplyAll;
}
/**
* @dev Indicates whether any token exist with a given id, or not.
*/
function exists(uint256 id) public view virtual returns (bool) {
return totalSupply(id) > 0;
}
/**
* @dev See {ERC1155-_update}.
*/
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal virtual override {
super._update(from, to, ids, values);
if (from == address(0)) {
uint256 totalMintValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply[ids[i]] += value;
totalMintValue += value;
}
// Overflow check required: The rest of the code assumes that totalSupplyAll never overflows
_totalSupplyAll += totalMintValue;
}
if (to == address(0)) {
uint256 totalBurnValue = 0;
for (uint256 i = 0; i < ids.length; ++i) {
uint256 value = values[i];
unchecked {
// Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i])
_totalSupply[ids[i]] -= value;
// Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
totalBurnValue += value;
}
}
unchecked {
// Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
_totalSupplyAll -= totalBurnValue;
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.20;
import {IERC1155} from "../IERC1155.sol";
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
*/
interface IERC1155MetadataURI is IERC1155 {
/**
* @dev Returns the URI for token type `id`.
*
* If the `\{id\}` substring is present in the URI, it must be replaced by
* clients with the actual token type ID.
*/
function uri(uint256 id) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";
/**
* @dev Collection of functions related to array types.
*/
library Arrays {
using StorageSlot for bytes32;
/**
* @dev Searches a sorted `array` and returns the first index that contains
* a value greater or equal to `element`. If no such index exists (i.e. all
* values in the array are strictly less than `element`), the array length is
* returned. Time complexity O(log n).
*
* `array` is expected to be sorted in ascending order, and to contain no
* repeated elements.
*/
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getAddressSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getBytes32Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getUint256Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
}// 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC165 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* 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[EIP 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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./EntropyStructs.sol";
interface EntropyEvents {
event Registered(EntropyStructs.ProviderInfo provider);
event Requested(EntropyStructs.Request request);
event RequestedWithCallback(
address indexed provider,
address indexed requestor,
uint64 indexed sequenceNumber,
bytes32 userRandomNumber,
EntropyStructs.Request request
);
event Revealed(
EntropyStructs.Request request,
bytes32 userRevelation,
bytes32 providerRevelation,
bytes32 blockHash,
bytes32 randomNumber
);
event RevealedWithCallback(
EntropyStructs.Request request,
bytes32 userRandomNumber,
bytes32 providerRevelation,
bytes32 randomNumber
);
event ProviderFeeUpdated(address provider, uint128 oldFee, uint128 newFee);
event ProviderUriUpdated(address provider, bytes oldUri, bytes newUri);
event ProviderFeeManagerUpdated(
address provider,
address oldFeeManager,
address newFeeManager
);
event Withdrawal(
address provider,
address recipient,
uint128 withdrawnAmount
);
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
contract EntropyStructs {
struct ProviderInfo {
uint128 feeInWei;
uint128 accruedFeesInWei;
// The commitment that the provider posted to the blockchain, and the sequence number
// where they committed to this. This value is not advanced after the provider commits,
// and instead is stored to help providers track where they are in the hash chain.
bytes32 originalCommitment;
uint64 originalCommitmentSequenceNumber;
// Metadata for the current commitment. Providers may optionally use this field to help
// manage rotations (i.e., to pick the sequence number from the correct hash chain).
bytes commitmentMetadata;
// Optional URI where clients can retrieve revelations for the provider.
// Client SDKs can use this field to automatically determine how to retrieve random values for each provider.
// TODO: specify the API that must be implemented at this URI
bytes uri;
// The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).
// The contract maintains the invariant that sequenceNumber <= endSequenceNumber.
// If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.
uint64 endSequenceNumber;
// The sequence number that will be assigned to the next inbound user request.
uint64 sequenceNumber;
// The current commitment represents an index/value in the provider's hash chain.
// These values are used to verify requests for future sequence numbers. Note that
// currentCommitmentSequenceNumber < sequenceNumber.
//
// The currentCommitment advances forward through the provider's hash chain as values
// are revealed on-chain.
bytes32 currentCommitment;
uint64 currentCommitmentSequenceNumber;
// An address that is authorized to set / withdraw fees on behalf of this provider.
address feeManager;
}
struct Request {
// Storage slot 1 //
address provider;
uint64 sequenceNumber;
// The number of hashes required to verify the provider revelation.
uint32 numHashes;
// Storage slot 2 //
// The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by
// eliminating 1 store.
bytes32 commitment;
// Storage slot 3 //
// The number of the block where this request was created.
// Note that we're using a uint64 such that we have an additional space for an address and other fields in
// this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the
// blocks ever generated.
uint64 blockNumber;
// The address that requested this random number.
address requester;
// If true, incorporate the blockhash of blockNumber into the generated random value.
bool useBlockhash;
// If true, the requester will be called back with the generated random value.
bool isRequestWithCallback;
// There are 2 remaining bytes of free space in this slot.
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./EntropyEvents.sol";
interface IEntropy is EntropyEvents {
// Register msg.sender as a randomness provider. The arguments are the provider's configuration parameters
// and initial commitment. Re-registering the same provider rotates the provider's commitment (and updates
// the feeInWei).
//
// chainLength is the number of values in the hash chain *including* the commitment, that is, chainLength >= 1.
function register(
uint128 feeInWei,
bytes32 commitment,
bytes calldata commitmentMetadata,
uint64 chainLength,
bytes calldata uri
) external;
// Withdraw a portion of the accumulated fees for the provider msg.sender.
// Calling this function will transfer `amount` wei to the caller (provided that they have accrued a sufficient
// balance of fees in the contract).
function withdraw(uint128 amount) external;
// Withdraw a portion of the accumulated fees for provider. The msg.sender must be the fee manager for this provider.
// Calling this function will transfer `amount` wei to the caller (provided that they have accrued a sufficient
// balance of fees in the contract).
function withdrawAsFeeManager(address provider, uint128 amount) external;
// As a user, request a random number from `provider`. Prior to calling this method, the user should
// generate a random number x and keep it secret. The user should then compute hash(x) and pass that
// as the userCommitment argument. (You may call the constructUserCommitment method to compute the hash.)
//
// This method returns a sequence number. The user should pass this sequence number to
// their chosen provider (the exact method for doing so will depend on the provider) to retrieve the provider's
// number. The user should then call fulfillRequest to construct the final random number.
//
// This method will revert unless the caller provides a sufficient fee (at least getFee(provider)) as msg.value.
// Note that excess value is *not* refunded to the caller.
function request(
address provider,
bytes32 userCommitment,
bool useBlockHash
) external payable returns (uint64 assignedSequenceNumber);
// Request a random number. The method expects the provider address and a secret random number
// in the arguments. It returns a sequence number.
//
// The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
// The `entropyCallback` method on that interface will receive a callback with the generated random number.
//
// This method will revert unless the caller provides a sufficient fee (at least getFee(provider)) as msg.value.
// Note that excess value is *not* refunded to the caller.
function requestWithCallback(
address provider,
bytes32 userRandomNumber
) external payable returns (uint64 assignedSequenceNumber);
// Fulfill a request for a random number. This method validates the provided userRandomness and provider's proof
// against the corresponding commitments in the in-flight request. If both values are validated, this function returns
// the corresponding random number.
//
// Note that this function can only be called once per in-flight request. Calling this function deletes the stored
// request information (so that the contract doesn't use a linear amount of storage in the number of requests).
// If you need to use the returned random number more than once, you are responsible for storing it.
function reveal(
address provider,
uint64 sequenceNumber,
bytes32 userRevelation,
bytes32 providerRevelation
) external returns (bytes32 randomNumber);
// Fulfill a request for a random number. This method validates the provided userRandomness
// and provider's revelation against the corresponding commitment in the in-flight request. If both values are validated
// and the requestor address is a contract address, this function calls the requester's entropyCallback method with the
// sequence number, provider address and the random number as arguments. Else if the requestor is an EOA, it won't call it.
//
// Note that this function can only be called once per in-flight request. Calling this function deletes the stored
// request information (so that the contract doesn't use a linear amount of storage in the number of requests).
// If you need to use the returned random number more than once, you are responsible for storing it.
//
// Anyone can call this method to fulfill a request, but the callback will only be made to the original requester.
function revealWithCallback(
address provider,
uint64 sequenceNumber,
bytes32 userRandomNumber,
bytes32 providerRevelation
) external;
function getProviderInfo(
address provider
) external view returns (EntropyStructs.ProviderInfo memory info);
function getDefaultProvider() external view returns (address provider);
function getRequest(
address provider,
uint64 sequenceNumber
) external view returns (EntropyStructs.Request memory req);
function getFee(address provider) external view returns (uint128 feeAmount);
function getAccruedPythFees()
external
view
returns (uint128 accruedPythFeesInWei);
function setProviderFee(uint128 newFeeInWei) external;
function setProviderFeeAsFeeManager(
address provider,
uint128 newFeeInWei
) external;
function setProviderUri(bytes calldata newUri) external;
// Set manager as the fee manager for the provider msg.sender.
// After calling this function, manager will be able to set the provider's fees and withdraw them.
// Only one address can be the fee manager for a provider at a time -- calling this function again with a new value
// will override the previous value. Call this function with the all-zero address to disable the fee manager role.
function setFeeManager(address manager) external;
function constructUserCommitment(
bytes32 userRandomness
) external pure returns (bytes32 userCommitment);
function combineRandomValues(
bytes32 userRandomness,
bytes32 providerRandomness,
bytes32 blockHash
) external pure returns (bytes32 combinedRandomness);
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
abstract contract IEntropyConsumer {
// This method is called by Entropy to provide the random number to the consumer.
// It asserts that the msg.sender is the Entropy contract. It is not meant to be
// override by the consumer.
function _entropyCallback(
uint64 sequence,
address provider,
bytes32 randomNumber
) external {
address entropy = getEntropy();
require(entropy != address(0), "Entropy address not set");
require(msg.sender == entropy, "Only Entropy can call this function");
entropyCallback(sequence, provider, randomNumber);
}
// getEntropy returns Entropy contract address. The method is being used to check that the
// callback is indeed from Entropy contract. The consumer is expected to implement this method.
// Entropy address can be found here - https://docs.pyth.network/entropy/contract-addresses
function getEntropy() internal view virtual returns (address);
// This method is expected to be implemented by the consumer to handle the random number.
// It will be called by _entropyCallback after _entropyCallback ensures that the call is
// indeed from Entropy contract.
function entropyCallback(
uint64 sequence,
address provider,
bytes32 randomNumber
) internal virtual;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
interface IERC2981Royalties {
function royaltyInfo(
uint256 _tokenId,
uint256 _value
) external view returns (address _receiver, uint256 _royaltyAmount);
}
/// @dev This is a contract used to add ERC2981 support to ERC721 and 1155
abstract contract ERC2981Base is ERC165, IERC2981Royalties {
struct RoyaltyInfo {
address recipient;
uint24 amount;
}
/// @inheritdoc ERC165
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC2981Royalties).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import '@openzeppelin/contracts/token/ERC1155/ERC1155.sol';
import '@openzeppelin/contracts/access/AccessControl.sol';
import '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol';
import '@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol';
import './ERC2981Base.sol';
import './libs/SafeMath.sol';
import './libs/SignedSafeMath.sol';
import './interfaces/IBlast.sol';
// import 'hardhat/console.sol';
contract Gangster is ERC1155, AccessControl, ERC1155Burnable, ERC1155Supply, ERC2981Base {
using SafeMath for uint256;
using SignedSafeMath for int256;
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
bytes32 public constant URI_SETTER_ROLE = keccak256('URI_SETTER_ROLE');
bytes32 public constant MINTER_ROLE = keccak256('MINTER_ROLE');
RoyaltyInfo private _royalties;
address private gasFeeOperator_;
string public name = 'Gangster';
string public symbol = 'Gangster';
constructor(address defaultAdmin, address minter) ERC1155('') {
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
_grantRole(URI_SETTER_ROLE, defaultAdmin);
_grantRole(MINTER_ROLE, defaultAdmin);
_grantRole(MINTER_ROLE, minter);
// BLAST.configureClaimableGas();
}
/**
* Claim gas
*/
function claimGas(bool _maxOnly) public onlyRole(DEFAULT_ADMIN_ROLE) {
require(gasFeeOperator_ != address(0), 'gasFee is not set');
if (_maxOnly) {
BLAST.claimMaxGas(address(this), gasFeeOperator_);
} else {
BLAST.claimAllGas(address(this), gasFeeOperator_);
}
}
function setURI(string memory newuri) public onlyRole(URI_SETTER_ROLE) {
_setURI(newuri);
}
/**
* set GasFeeOperator
*/
function setGasFeeOperator(address _gasFeeOperator) public onlyRole(DEFAULT_ADMIN_ROLE) {
gasFeeOperator_ = _gasFeeOperator;
}
/**
* @notice Pre-sale buy gangster
*/
function mint(address account, uint256 id, uint256 amount, bytes memory data) public onlyRole(MINTER_ROLE) {
_mint(account, id, amount, data);
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function approvalForWithdraw(address operator, bool approved) public onlyRole(DEFAULT_ADMIN_ROLE) {
_setApprovalForAll(address(this), operator, approved);
}
// The following functions are overrides required by Solidity.
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory values
) internal override(ERC1155, ERC1155Supply) {
super._update(from, to, ids, values);
}
// Value is in basis points so 10000 = 100% , 100 = 1% etc
function setRoyalties(address recipient, uint256 value) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(value <= 10000, 'ERC2981Royalties: Too high');
_royalties = RoyaltyInfo(recipient, uint24(value));
}
function royaltyInfo(
uint256,
uint256 value
) external view override returns (address receiver, uint256 royaltyAmount) {
RoyaltyInfo memory royalties = _royalties;
receiver = royalties.recipient;
royaltyAmount = (value * royalties.amount) / 10000;
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC1155, AccessControl, ERC2981Base) returns (bool) {
return super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
interface IBlast {
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(
address contractAddress,
address recipientOfGas,
uint256 minClaimRateBips
) external returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(
address contractAddress,
address recipientOfGas,
uint256 gasToClaim,
uint256 gasSecondsToConsume
) external returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(
address contractAddress
) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}
interface IBlastPoints {
function configurePointsOperator(address operator) external;
function configurePointsOperatorOnBehalf(address contractAddress, address operator) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SignedSafeMath {
int256 private constant _INT256_MIN = -2 ** 255;
/**
* @dev Returns the multiplication of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
require(!(a == -1 && b == _INT256_MIN), 'SignedSafeMath: multiplication overflow');
int256 c = a * b;
require(c / a == b, 'SignedSafeMath: multiplication overflow');
return c;
}
/**
* @dev Returns the integer division of two signed integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0, 'SignedSafeMath: division by zero');
require(!(b == -1 && a == _INT256_MIN), 'SignedSafeMath: division overflow');
int256 c = a / b;
return c;
}
/**
* @dev Returns the subtraction of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a), 'SignedSafeMath: subtraction overflow');
return c;
}
/**
* @dev Returns the addition of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a), 'SignedSafeMath: addition overflow');
return c;
}
function toUInt256(int256 a) internal pure returns (uint256) {
require(a >= 0, 'Integer < 0');
return uint256(a);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SignerLib {
/**
***************************
Internal Function
***************************
*/
/**
* @notice Verify signature
*/
function verifyAddressSigner(address signer, bytes32 message, bytes memory sig) internal pure returns (bool) {
return signer == recoverSignerFromSignature(message, sig);
}
//function to get the public address of the signer
function recoverSignerFromSignature(bytes32 message, bytes memory sig) internal pure returns (address) {
require(sig.length == 65);
uint8 v;
bytes32 r;
bytes32 s;
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
return ecrecover(message, v, r, s);
}
// Builds a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 _hashedMessage) internal pure returns (bytes32) {
bytes memory prefix = '\x19Ethereum Signed Message:\n32';
bytes32 prefixedHashMessage = keccak256(abi.encodePacked(prefix, _hashedMessage));
return prefixedHashMessage;
}
}{
"evmVersion": "paris",
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"_gangster","type":"address"},{"internalType":"address","name":"_signer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"entropy","type":"address"},{"indexed":false,"internalType":"uint64","name":"sequence","type":"uint64"},{"indexed":false,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"bytes32","name":"randomNumber","type":"bytes32"}],"name":"EntropyResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"phaseId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"RequestMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"phaseId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"RevealMint","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"randomNumber","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"_calculateMintResult","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"randomNumber","type":"uint256"}],"name":"_calculateProbability","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sequence","type":"uint64"},{"internalType":"address","name":"provider","type":"address"},{"internalType":"bytes32","name":"randomNumber","type":"bytes32"}],"name":"_entropyCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_maxOnly","type":"bool"}],"name":"claimGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emegencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"name":"getMintValues","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_sequence","type":"uint64"},{"internalType":"bytes32","name":"_randomNumber","type":"bytes32"}],"name":"manualCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"phaseId_","type":"uint256"},{"internalType":"uint16","name":"amount_","type":"uint16"},{"internalType":"bytes32","name":"userRandomNumber_","type":"bytes32"},{"internalType":"bytes","name":"sig_","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"mintData","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint16","name":"amount","type":"uint16"},{"internalType":"bytes32","name":"randomNumber","type":"bytes32"},{"internalType":"uint256","name":"phaseId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintPhase","outputs":[{"internalType":"uint32","name":"MAX_PER_BATCH","type":"uint32"},{"internalType":"uint256","name":"BASE_PRICE","type":"uint256"},{"internalType":"bool","name":"status","type":"bool"},{"internalType":"bool","name":"whitelistedOnly","type":"bool"},{"internalType":"uint32","name":"MIN_VALUE","type":"uint32"},{"internalType":"uint32","name":"MAX_VALUE","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"probabilities","outputs":[{"internalType":"uint256","name":"probability","type":"uint256"},{"internalType":"uint256","name":"gangsterReward","type":"uint256"},{"internalType":"uint256","name":"MAX_PROBAILITY","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"provider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestedRandomNumber","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gasFeeOperator","type":"address"}],"name":"setGasFeeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setWorker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_phaseId","type":"uint256"},{"internalType":"uint32","name":"_maxPerBatch","type":"uint32"},{"internalType":"uint256","name":"_basePrice","type":"uint256"},{"internalType":"bool","name":"_status","type":"bool"},{"internalType":"bool","name":"_whitelistedOnly","type":"bool"}],"name":"updatePhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_probability","type":"uint256[]"},{"internalType":"uint256[]","name":"_gangsterReward","type":"uint256[]"}],"name":"updateProbability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_entropy","type":"address"},{"internalType":"address","name":"_provider","type":"address"}],"name":"updatePyth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040527398046bd286715d3b0bc227dd7a956b83d8978603600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200006657600080fd5b506040516200404f3803806200404f83398181016040528101906200008c919062000343565b82600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620001025760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000f99190620003b0565b60405180910390fd5b62000113816200021560201b60201c565b5081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff16634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b158015620001f357600080fd5b505af115801562000208573d6000803e3d6000fd5b50505050505050620003cd565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200030b82620002de565b9050919050565b6200031d81620002fe565b81146200032957600080fd5b50565b6000815190506200033d8162000312565b92915050565b6000806000606084860312156200035f576200035e620002d9565b5b60006200036f868287016200032c565b935050602062000382868287016200032c565b925050604062000395868287016200032c565b9150509250925092565b620003aa81620002fe565b82525050565b6000602082019050620003c760008301846200039f565b92915050565b613c7280620003dd6000396000f3fe60806040526004361061016a5760003560e01c80639518d7c7116100d1578063cc9d56721161008a578063dbcd106611610064578063dbcd106614610522578063f2fde38b1461053e578063f5249be014610567578063f8833efd1461059057610171565b8063cc9d567214610475578063ced72f87146104b5578063d045586d146104e057610171565b80639518d7c71461038f57806397d75776146103b857806398795ee6146103e3578063b09191ad146103fa578063b943cbbb14610423578063c26f6d441461044c57610171565b806352a5f1f81161012357806352a5f1f81461029557806358476046146102be5780636443ef1b146102e75780636605bfda14610324578063715018a61461034d5780638da5cb5b1461036457610171565b8063051f7e4514610173578063085d4883146101b05780630d2ae5c9146101db57806320a38b7014610204578063328d7cc8146102415780633ccfd60b1461027e57610171565b3661017157005b005b34801561017f57600080fd5b5061019a60048036038101906101959190612362565b6105cf565b6040516101a791906123b2565b60405180910390f35b3480156101bc57600080fd5b506101c56105f6565b6040516101d2919061240e565b60405180910390f35b3480156101e757600080fd5b5061020260048036038101906101fd9190612455565b61061c565b005b34801561021057600080fd5b5061022b600480360381019061022691906124ae565b610668565b60405161023891906125a3565b60405180910390f35b34801561024d57600080fd5b50610268600480360381019061026391906125f1565b6106ea565b60405161027591906125a3565b60405180910390f35b34801561028a57600080fd5b506102936107bd565b005b3480156102a157600080fd5b506102bc60048036038101906102b79190612631565b61090a565b005b3480156102ca57600080fd5b506102e560048036038101906102e09190612684565b610a04565b005b3480156102f357600080fd5b5061030e600480360381019061030991906126c4565b610b70565b60405161031b9190612700565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190612455565b610c10565b005b34801561035957600080fd5b50610362610c5c565b005b34801561037057600080fd5b50610379610c70565b604051610386919061240e565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b1919061271b565b610c99565b005b3480156103c457600080fd5b506103cd610f60565b6040516103da91906127ba565b60405180910390f35b3480156103ef57600080fd5b506103f8610f78565b005b34801561040657600080fd5b50610421600480360381019061041c9190612849565b611012565b005b34801561042f57600080fd5b5061044a600480360381019061044591906128c4565b6110cd565b005b34801561045857600080fd5b50610473600480360381019061046e9190612455565b6112d7565b005b34801561048157600080fd5b5061049c600480360381019061049791906124ae565b611323565b6040516104ac949392919061291d565b60405180910390f35b3480156104c157600080fd5b506104ca611381565b6040516104d79190612700565b60405180910390f35b3480156104ec57600080fd5b50610507600480360381019061050291906126c4565b611458565b60405161051996959493929190612980565b60405180910390f35b61053c60048036038101906105379190612b53565b6114de565b005b34801561054a57600080fd5b5061056560048036038101906105609190612455565b611aae565b005b34801561057357600080fd5b5061058e60048036038101906105899190612c9e565b611b34565b005b34801561059c57600080fd5b506105b760048036038101906105b291906126c4565b611c48565b6040516105c693929190612d16565b60405180910390f35b600a6020528060005260406000206000915054906101000a900467ffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610624611c82565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600960008367ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206001018054806020026020016040519081016040528092919081815260200182805480156106de57602002820191906000526020600020905b8154815260200190600101908083116106ca575b50505050509050919050565b606060008267ffffffffffffffff81111561070857610707612a28565b5b6040519080825280602002602001820160405280156107365781602001602082028036833780820191505090505b50905060005b838161ffff1610156107b25760006103e8826103e861075b9190612eaf565b876107669190612f29565b6107709190612f5a565b905061077b81610b70565b838361ffff168151811061079257610791612f8b565b5b6020026020010181815250505080806107aa90612fba565b91505061073c565b508091505092915050565b6107c5611c82565b60004711610808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ff90613041565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610899576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610890906130ad565b60405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610906573d6000803e3d6000fd5b5050565b6000610914611d09565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097c90613119565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ea906131ab565b60405180910390fd5b6109fe848484611d33565b50505050565b610a0c611c82565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7290613217565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae190613217565b60405180910390fd5b81600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000806000905060005b600b80549050811015610c0457600b8181548110610b9b57610b9a612f8b565b5b90600052602060002090600302016000015482610bb89190613237565b915081841015610bf157600b8181548110610bd657610bd5612f8b565b5b90600052602060002090600302016001015492505050610c0b565b8080610bfc9061326b565b915050610b7a565b5060009150505b919050565b610c18611c82565b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610c64611c82565b610c6e6000612054565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f17c4cce12998322f805ff6c39786651b347a39141c4e8e47767fda085581cde33383600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684604051610cf094939291906132b3565b60405180910390a1600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610d39612118565b73ffffffffffffffffffffffffffffffffffffffff1614610d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8690613344565b60405180910390fd5b6000600960008467ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a900461ffff169050600080846002015460001c14610e45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3c906133b0565b60405180910390fd5b8484600201819055506000610e618660001c8461ffff166106ea565b9050610e6c81612120565b915080856001019080519060200190610e869291906122ae565b50600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663731133e9856001856040518463ffffffff1660e01b8152600401610ee793929190613442565b600060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b505050507f4573b1c4a81e563013c3bfa32c89bd049df6313564234d6a1c7c233a731f77fa848360018a604051610f4f949392919061348c565b60405180910390a150505050505050565b73430000000000000000000000000000000000000281565b610f80611c82565b60004711610fc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fba90613041565b60405180910390fd5b60003390508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f1935050505015801561100e573d6000803e3d6000fd5b5050565b61101a611c82565b836008600087815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff160217905550826008600087815260200190815260200160002060010181905550816008600087815260200190815260200160002060020160006101000a81548160ff021916908315150217905550806008600087815260200190815260200160002060020160016101000a81548160ff0219169083151502179055505050505050565b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061351d565b60405180910390fd5b801561121e5773430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff1663662aa11d30600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b81526004016111d592919061353d565b6020604051808303816000875af11580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611218919061357b565b506112d4565b73430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff1663954fa5ee30600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b815260040161128f92919061353d565b6020604051808303816000875af11580156112ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d2919061357b565b505b50565b6112df611c82565b80600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60096020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060020154908060030154905084565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b88c9148600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401611400919061240e565b602060405180830381865afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144191906135f0565b6fffffffffffffffffffffffffffffffff16905090565b60086020528060005260406000206000915090508060000160009054906101000a900463ffffffff16908060010154908060020160009054906101000a900460ff16908060020160019054906101000a900460ff16908060020160029054906101000a900463ffffffff16908060020160069054906101000a900463ffffffff16905086565b6008600085815260200190815260200160002060020160009054906101000a900460ff16611541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153890613669565b60405180910390fd5b8261ffff166008600086815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1610156115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab906136d5565b60405180910390fd5b6000600a600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614611628576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161f90613741565b60405180910390fd5b600060086000868152602001908152602001600020600101548461ffff166116509190613761565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b88c9148600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016116d1919061240e565b602060405180830381865afa1580156116ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171291906135f0565b6fffffffffffffffffffffffffffffffff169050600082826117349190613237565b90506000600860008981526020019081526020016000206001015411156117995780341015611798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178f906137ef565b60405180910390fd5b5b6008600088815260200190815260200160002060020160019054906101000a900460ff16156118895760006117f9338989896040516020016117de94939291906138cf565b60405160208183030381529060405280519060200120612172565b90506118488186600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166121e49092919063ffffffff16565b611887576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187e90613969565b60405180910390fd5b505b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166319cb825f84600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896040518463ffffffff1660e01b815260040161190b929190613989565b60206040518083038185885af1158015611929573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061194e91906139c7565b905080600a600088815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555033600960008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600960008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000160146101000a81548161ffff021916908361ffff16021790555087600960008367ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600301819055507fc332ce7c560e1184b0358aa14014f7fbbbf083aa8611e28d4812bafb7b30861933888a84604051611a9c9493929190613a25565b60405180910390a15050505050505050565b611ab6611c82565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b285760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611b1f919061240e565b60405180910390fd5b611b3181612054565b50565b611b3c611c82565b6103e8611b4883612120565b14611b88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7f90613ab6565b60405180910390fd5b60005b8251811015611c4357600b6040518060600160405280858481518110611bb457611bb3612f8b565b5b60200260200101518152602001848481518110611bd457611bd3612f8b565b5b602002602001015181526020016103e8815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550508080611c3b9061326b565b915050611b8b565b505050565b600b8181548110611c5857600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b611c8a612118565b73ffffffffffffffffffffffffffffffffffffffff16611ca8610c70565b73ffffffffffffffffffffffffffffffffffffffff1614611d0757611ccb612118565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611cfe919061240e565b60405180910390fd5b565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f17c4cce12998322f805ff6c39786651b347a39141c4e8e47767fda085581cde33384600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684604051611d8a94939291906132b3565b60405180910390a1600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd3612118565b73ffffffffffffffffffffffffffffffffffffffff16148015611e4357508173ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990613b22565b60405180910390fd5b6000600960008567ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a900461ffff169050600080846002015460001c14611f38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f2f906133b0565b60405180910390fd5b8484600201819055506000611f548660001c8461ffff166106ea565b9050611f5f81612120565b915080856001019080519060200190611f799291906122ae565b50600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663731133e9856001856040518463ffffffff1660e01b8152600401611fda93929190613442565b600060405180830381600087803b158015611ff457600080fd5b505af1158015612008573d6000803e3d6000fd5b505050507f4573b1c4a81e563013c3bfa32c89bd049df6313564234d6a1c7c233a731f77fa848360018b604051612042949392919061348c565b60405180910390a15050505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b600080600090505b825181101561216c5782818151811061214457612143612f8b565b5b6020026020010151826121579190613237565b915080806121649061326b565b915050612128565b50919050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081846040516020016121c2929190613bb3565b6040516020818303038152906040528051906020012090508092505050919050565b60006121f08383612227565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490509392505050565b6000604182511461223757600080fd5b60008060006020850151915060408501519050606085015160001a9250600186848484604051600081526020016040526040516122779493929190613bf7565b6020604051602081039080840390855afa158015612299573d6000803e3d6000fd5b50505060206040510351935050505092915050565b8280548282559060005260206000209081019282156122ea579160200282015b828111156122e95782518255916020019190600101906122ce565b5b5090506122f791906122fb565b5090565b5b808211156123145760008160009055506001016122fc565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61233f8161232c565b811461234a57600080fd5b50565b60008135905061235c81612336565b92915050565b60006020828403121561237857612377612322565b5b60006123868482850161234d565b91505092915050565b600067ffffffffffffffff82169050919050565b6123ac8161238f565b82525050565b60006020820190506123c760008301846123a3565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123f8826123cd565b9050919050565b612408816123ed565b82525050565b600060208201905061242360008301846123ff565b92915050565b612432816123ed565b811461243d57600080fd5b50565b60008135905061244f81612429565b92915050565b60006020828403121561246b5761246a612322565b5b600061247984828501612440565b91505092915050565b61248b8161238f565b811461249657600080fd5b50565b6000813590506124a881612482565b92915050565b6000602082840312156124c4576124c3612322565b5b60006124d284828501612499565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61251a81612507565b82525050565b600061252c8383612511565b60208301905092915050565b6000602082019050919050565b6000612550826124db565b61255a81856124e6565b9350612565836124f7565b8060005b8381101561259657815161257d8882612520565b975061258883612538565b925050600181019050612569565b5085935050505092915050565b600060208201905081810360008301526125bd8184612545565b905092915050565b6125ce81612507565b81146125d957600080fd5b50565b6000813590506125eb816125c5565b92915050565b6000806040838503121561260857612607612322565b5b6000612616858286016125dc565b9250506020612627858286016125dc565b9150509250929050565b60008060006060848603121561264a57612649612322565b5b600061265886828701612499565b935050602061266986828701612440565b925050604061267a8682870161234d565b9150509250925092565b6000806040838503121561269b5761269a612322565b5b60006126a985828601612440565b92505060206126ba85828601612440565b9150509250929050565b6000602082840312156126da576126d9612322565b5b60006126e8848285016125dc565b91505092915050565b6126fa81612507565b82525050565b600060208201905061271560008301846126f1565b92915050565b6000806040838503121561273257612731612322565b5b600061274085828601612499565b92505060206127518582860161234d565b9150509250929050565b6000819050919050565b600061278061277b612776846123cd565b61275b565b6123cd565b9050919050565b600061279282612765565b9050919050565b60006127a482612787565b9050919050565b6127b481612799565b82525050565b60006020820190506127cf60008301846127ab565b92915050565b600063ffffffff82169050919050565b6127ee816127d5565b81146127f957600080fd5b50565b60008135905061280b816127e5565b92915050565b60008115159050919050565b61282681612811565b811461283157600080fd5b50565b6000813590506128438161281d565b92915050565b600080600080600060a0868803121561286557612864612322565b5b6000612873888289016125dc565b9550506020612884888289016127fc565b9450506040612895888289016125dc565b93505060606128a688828901612834565b92505060806128b788828901612834565b9150509295509295909350565b6000602082840312156128da576128d9612322565b5b60006128e884828501612834565b91505092915050565b600061ffff82169050919050565b612908816128f1565b82525050565b6129178161232c565b82525050565b600060808201905061293260008301876123ff565b61293f60208301866128ff565b61294c604083018561290e565b61295960608301846126f1565b95945050505050565b61296b816127d5565b82525050565b61297a81612811565b82525050565b600060c0820190506129956000830189612962565b6129a260208301886126f1565b6129af6040830187612971565b6129bc6060830186612971565b6129c96080830185612962565b6129d660a0830184612962565b979650505050505050565b6129ea816128f1565b81146129f557600080fd5b50565b600081359050612a07816129e1565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612a6082612a17565b810181811067ffffffffffffffff82111715612a7f57612a7e612a28565b5b80604052505050565b6000612a92612318565b9050612a9e8282612a57565b919050565b600067ffffffffffffffff821115612abe57612abd612a28565b5b612ac782612a17565b9050602081019050919050565b82818337600083830152505050565b6000612af6612af184612aa3565b612a88565b905082815260208101848484011115612b1257612b11612a12565b5b612b1d848285612ad4565b509392505050565b600082601f830112612b3a57612b39612a0d565b5b8135612b4a848260208601612ae3565b91505092915050565b60008060008060808587031215612b6d57612b6c612322565b5b6000612b7b878288016125dc565b9450506020612b8c878288016129f8565b9350506040612b9d8782880161234d565b925050606085013567ffffffffffffffff811115612bbe57612bbd612327565b5b612bca87828801612b25565b91505092959194509250565b600067ffffffffffffffff821115612bf157612bf0612a28565b5b602082029050602081019050919050565b600080fd5b6000612c1a612c1584612bd6565b612a88565b90508083825260208201905060208402830185811115612c3d57612c3c612c02565b5b835b81811015612c665780612c5288826125dc565b845260208401935050602081019050612c3f565b5050509392505050565b600082601f830112612c8557612c84612a0d565b5b8135612c95848260208601612c07565b91505092915050565b60008060408385031215612cb557612cb4612322565b5b600083013567ffffffffffffffff811115612cd357612cd2612327565b5b612cdf85828601612c70565b925050602083013567ffffffffffffffff811115612d0057612cff612327565b5b612d0c85828601612c70565b9150509250929050565b6000606082019050612d2b60008301866126f1565b612d3860208301856126f1565b612d4560408301846126f1565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115612dd357808604811115612daf57612dae612d4d565b5b6001851615612dbe5780820291505b8081029050612dcc85612d7c565b9450612d93565b94509492505050565b600082612dec5760019050612ea8565b81612dfa5760009050612ea8565b8160018114612e105760028114612e1a57612e49565b6001915050612ea8565b60ff841115612e2c57612e2b612d4d565b5b8360020a915084821115612e4357612e42612d4d565b5b50612ea8565b5060208310610133831016604e8410600b8410161715612e7e5782820a905083811115612e7957612e78612d4d565b5b612ea8565b612e8b8484846001612d89565b92509050818404811115612ea257612ea1612d4d565b5b81810290505b9392505050565b6000612eba82612507565b9150612ec5836128f1565b9250612ef27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612ddc565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612f3482612507565b9150612f3f83612507565b925082612f4f57612f4e612efa565b5b828204905092915050565b6000612f6582612507565b9150612f7083612507565b925082612f8057612f7f612efa565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000612fc5826128f1565b915061ffff8203612fd957612fd8612d4d565b5b600182019050919050565b600082825260208201905092915050565b7f4e6f7468696e6720746f20776974686472617700000000000000000000000000600082015250565b600061302b601383612fe4565b915061303682612ff5565b602082019050919050565b6000602082019050818103600083015261305a8161301e565b9050919050565b7f5472656173757279206973206e6f742073657400000000000000000000000000600082015250565b6000613097601383612fe4565b91506130a282613061565b602082019050919050565b600060208201905081810360008301526130c68161308a565b9050919050565b7f456e74726f70792061646472657373206e6f7420736574000000000000000000600082015250565b6000613103601783612fe4565b915061310e826130cd565b602082019050919050565b60006020820190508181036000830152613132816130f6565b9050919050565b7f4f6e6c7920456e74726f70792063616e2063616c6c20746869732066756e637460008201527f696f6e0000000000000000000000000000000000000000000000000000000000602082015250565b6000613195602383612fe4565b91506131a082613139565b604082019050919050565b600060208201905081810360008301526131c481613188565b9050919050565b7f4e4f545f414c4c4f5745445f5a45524f5f414444524553530000000000000000600082015250565b6000613201601883612fe4565b915061320c826131cb565b602082019050919050565b60006020820190508181036000830152613230816131f4565b9050919050565b600061324282612507565b915061324d83612507565b925082820190508082111561326557613264612d4d565b5b92915050565b600061327682612507565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036132a8576132a7612d4d565b5b600182019050919050565b60006080820190506132c860008301876123ff565b6132d560208301866123a3565b6132e260408301856123ff565b6132ef606083018461290e565b95945050505050565b7f43616c6c6572206973206e6f7420776f726b6572000000000000000000000000600082015250565b600061332e601483612fe4565b9150613339826132f8565b602082019050919050565b6000602082019050818103600083015261335d81613321565b9050919050565b7f4d696e742069732072657665616c656400000000000000000000000000000000600082015250565b600061339a601083612fe4565b91506133a582613364565b602082019050919050565b600060208201905081810360008301526133c98161338d565b9050919050565b6000819050919050565b60006133f56133f06133eb846133d0565b61275b565b612507565b9050919050565b613405816133da565b82525050565b600082825260208201905092915050565b50565b600061342c60008361340b565b91506134378261341c565b600082019050919050565b600060808201905061345760008301866123ff565b61346460208301856133fc565b61347160408301846126f1565b81810360608301526134828161341f565b9050949350505050565b60006080820190506134a160008301876123ff565b6134ae60208301866126f1565b6134bb60408301856133fc565b6134c860608301846123a3565b95945050505050565b7f676173466565206973206e6f7420736574000000000000000000000000000000600082015250565b6000613507601183612fe4565b9150613512826134d1565b602082019050919050565b60006020820190508181036000830152613536816134fa565b9050919050565b600060408201905061355260008301856123ff565b61355f60208301846123ff565b9392505050565b600081519050613575816125c5565b92915050565b60006020828403121561359157613590612322565b5b600061359f84828501613566565b91505092915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6135cd816135a8565b81146135d857600080fd5b50565b6000815190506135ea816135c4565b92915050565b60006020828403121561360657613605612322565b5b6000613614848285016135db565b91505092915050565b7f4d696e74207068617365206973206e6f7420617661696c61626c650000000000600082015250565b6000613653601b83612fe4565b915061365e8261361d565b602082019050919050565b6000602082019050818103600083015261368281613646565b9050919050565b7f4f766572206d6178207065722062617463680000000000000000000000000000600082015250565b60006136bf601283612fe4565b91506136ca82613689565b602082019050919050565b600060208201905081810360008301526136ee816136b2565b9050919050565b7f5261642069732075736564000000000000000000000000000000000000000000600082015250565b600061372b600b83612fe4565b9150613736826136f5565b602082019050919050565b6000602082019050818103600083015261375a8161371e565b9050919050565b600061376c82612507565b915061377783612507565b925082820261378581612507565b9150828204841483151761379c5761379b612d4d565b5b5092915050565b7f53656e64206d6f72652065746800000000000000000000000000000000000000600082015250565b60006137d9600d83612fe4565b91506137e4826137a3565b602082019050919050565b60006020820190508181036000830152613808816137cc565b9050919050565b60008160601b9050919050565b60006138278261380f565b9050919050565b60006138398261381c565b9050919050565b61385161384c826123ed565b61382e565b82525050565b6000819050919050565b61387261386d82612507565b613857565b82525050565b60008160f01b9050919050565b600061389082613878565b9050919050565b6138a86138a3826128f1565b613885565b82525050565b6000819050919050565b6138c96138c48261232c565b6138ae565b82525050565b60006138db8287613840565b6014820191506138eb8286613861565b6020820191506138fb8285613897565b60028201915061390b82846138b8565b60208201915081905095945050505050565b7f496e76616c6964207369676e6174757265000000000000000000000000000000600082015250565b6000613953601183612fe4565b915061395e8261391d565b602082019050919050565b6000602082019050818103600083015261398281613946565b9050919050565b600060408201905061399e60008301856123ff565b6139ab602083018461290e565b9392505050565b6000815190506139c181612482565b92915050565b6000602082840312156139dd576139dc612322565b5b60006139eb848285016139b2565b91505092915050565b6000613a0f613a0a613a05846128f1565b61275b565b612507565b9050919050565b613a1f816139f4565b82525050565b6000608082019050613a3a60008301876123ff565b613a476020830186613a16565b613a5460408301856126f1565b613a6160608301846123a3565b95945050505050565b7f496e76616c696420696e70757400000000000000000000000000000000000000600082015250565b6000613aa0600d83612fe4565b9150613aab82613a6a565b602082019050919050565b60006020820190508181036000830152613acf81613a93565b9050919050565b7f43616c6c6572206973206e6f7420656e74726f70790000000000000000000000600082015250565b6000613b0c601583612fe4565b9150613b1782613ad6565b602082019050919050565b60006020820190508181036000830152613b3b81613aff565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015613b76578082015181840152602081019050613b5b565b60008484015250505050565b6000613b8d82613b42565b613b978185613b4d565b9350613ba7818560208601613b58565b80840191505092915050565b6000613bbf8285613b82565b9150613bcb82846138b8565b6020820191508190509392505050565b600060ff82169050919050565b613bf181613bdb565b82525050565b6000608082019050613c0c600083018761290e565b613c196020830186613be8565b613c26604083018561290e565b613c33606083018461290e565b9594505050505056fea2646970667358221220977349813f9c4bd294b1a932fd9598a0c8f140239a5bc03a0060c7a541da729c64736f6c634300081400330000000000000000000000007866ac3933dca99b2e9a80f8948344a387a7bf620000000000000000000000003b920eb71418fb4a4e752b8c728caea582759057000000000000000000000000ec6d0c755c255f2ecb400f716a557270cead7d8f
Deployed Bytecode
0x60806040526004361061016a5760003560e01c80639518d7c7116100d1578063cc9d56721161008a578063dbcd106611610064578063dbcd106614610522578063f2fde38b1461053e578063f5249be014610567578063f8833efd1461059057610171565b8063cc9d567214610475578063ced72f87146104b5578063d045586d146104e057610171565b80639518d7c71461038f57806397d75776146103b857806398795ee6146103e3578063b09191ad146103fa578063b943cbbb14610423578063c26f6d441461044c57610171565b806352a5f1f81161012357806352a5f1f81461029557806358476046146102be5780636443ef1b146102e75780636605bfda14610324578063715018a61461034d5780638da5cb5b1461036457610171565b8063051f7e4514610173578063085d4883146101b05780630d2ae5c9146101db57806320a38b7014610204578063328d7cc8146102415780633ccfd60b1461027e57610171565b3661017157005b005b34801561017f57600080fd5b5061019a60048036038101906101959190612362565b6105cf565b6040516101a791906123b2565b60405180910390f35b3480156101bc57600080fd5b506101c56105f6565b6040516101d2919061240e565b60405180910390f35b3480156101e757600080fd5b5061020260048036038101906101fd9190612455565b61061c565b005b34801561021057600080fd5b5061022b600480360381019061022691906124ae565b610668565b60405161023891906125a3565b60405180910390f35b34801561024d57600080fd5b50610268600480360381019061026391906125f1565b6106ea565b60405161027591906125a3565b60405180910390f35b34801561028a57600080fd5b506102936107bd565b005b3480156102a157600080fd5b506102bc60048036038101906102b79190612631565b61090a565b005b3480156102ca57600080fd5b506102e560048036038101906102e09190612684565b610a04565b005b3480156102f357600080fd5b5061030e600480360381019061030991906126c4565b610b70565b60405161031b9190612700565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190612455565b610c10565b005b34801561035957600080fd5b50610362610c5c565b005b34801561037057600080fd5b50610379610c70565b604051610386919061240e565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b1919061271b565b610c99565b005b3480156103c457600080fd5b506103cd610f60565b6040516103da91906127ba565b60405180910390f35b3480156103ef57600080fd5b506103f8610f78565b005b34801561040657600080fd5b50610421600480360381019061041c9190612849565b611012565b005b34801561042f57600080fd5b5061044a600480360381019061044591906128c4565b6110cd565b005b34801561045857600080fd5b50610473600480360381019061046e9190612455565b6112d7565b005b34801561048157600080fd5b5061049c600480360381019061049791906124ae565b611323565b6040516104ac949392919061291d565b60405180910390f35b3480156104c157600080fd5b506104ca611381565b6040516104d79190612700565b60405180910390f35b3480156104ec57600080fd5b50610507600480360381019061050291906126c4565b611458565b60405161051996959493929190612980565b60405180910390f35b61053c60048036038101906105379190612b53565b6114de565b005b34801561054a57600080fd5b5061056560048036038101906105609190612455565b611aae565b005b34801561057357600080fd5b5061058e60048036038101906105899190612c9e565b611b34565b005b34801561059c57600080fd5b506105b760048036038101906105b291906126c4565b611c48565b6040516105c693929190612d16565b60405180910390f35b600a6020528060005260406000206000915054906101000a900467ffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610624611c82565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600960008367ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206001018054806020026020016040519081016040528092919081815260200182805480156106de57602002820191906000526020600020905b8154815260200190600101908083116106ca575b50505050509050919050565b606060008267ffffffffffffffff81111561070857610707612a28565b5b6040519080825280602002602001820160405280156107365781602001602082028036833780820191505090505b50905060005b838161ffff1610156107b25760006103e8826103e861075b9190612eaf565b876107669190612f29565b6107709190612f5a565b905061077b81610b70565b838361ffff168151811061079257610791612f8b565b5b6020026020010181815250505080806107aa90612fba565b91505061073c565b508091505092915050565b6107c5611c82565b60004711610808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ff90613041565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610899576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610890906130ad565b60405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610906573d6000803e3d6000fd5b5050565b6000610914611d09565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097c90613119565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ea906131ab565b60405180910390fd5b6109fe848484611d33565b50505050565b610a0c611c82565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7290613217565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610aea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae190613217565b60405180910390fd5b81600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000806000905060005b600b80549050811015610c0457600b8181548110610b9b57610b9a612f8b565b5b90600052602060002090600302016000015482610bb89190613237565b915081841015610bf157600b8181548110610bd657610bd5612f8b565b5b90600052602060002090600302016001015492505050610c0b565b8080610bfc9061326b565b915050610b7a565b5060009150505b919050565b610c18611c82565b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610c64611c82565b610c6e6000612054565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f17c4cce12998322f805ff6c39786651b347a39141c4e8e47767fda085581cde33383600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684604051610cf094939291906132b3565b60405180910390a1600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16610d39612118565b73ffffffffffffffffffffffffffffffffffffffff1614610d8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8690613344565b60405180910390fd5b6000600960008467ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a900461ffff169050600080846002015460001c14610e45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3c906133b0565b60405180910390fd5b8484600201819055506000610e618660001c8461ffff166106ea565b9050610e6c81612120565b915080856001019080519060200190610e869291906122ae565b50600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663731133e9856001856040518463ffffffff1660e01b8152600401610ee793929190613442565b600060405180830381600087803b158015610f0157600080fd5b505af1158015610f15573d6000803e3d6000fd5b505050507f4573b1c4a81e563013c3bfa32c89bd049df6313564234d6a1c7c233a731f77fa848360018a604051610f4f949392919061348c565b60405180910390a150505050505050565b73430000000000000000000000000000000000000281565b610f80611c82565b60004711610fc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fba90613041565b60405180910390fd5b60003390508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f1935050505015801561100e573d6000803e3d6000fd5b5050565b61101a611c82565b836008600087815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff160217905550826008600087815260200190815260200160002060010181905550816008600087815260200190815260200160002060020160006101000a81548160ff021916908315150217905550806008600087815260200190815260200160002060020160016101000a81548160ff0219169083151502179055505050505050565b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361115e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111559061351d565b60405180910390fd5b801561121e5773430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff1663662aa11d30600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b81526004016111d592919061353d565b6020604051808303816000875af11580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611218919061357b565b506112d4565b73430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff1663954fa5ee30600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b815260040161128f92919061353d565b6020604051808303816000875af11580156112ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d2919061357b565b505b50565b6112df611c82565b80600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60096020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060020154908060030154905084565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b88c9148600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401611400919061240e565b602060405180830381865afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144191906135f0565b6fffffffffffffffffffffffffffffffff16905090565b60086020528060005260406000206000915090508060000160009054906101000a900463ffffffff16908060010154908060020160009054906101000a900460ff16908060020160019054906101000a900460ff16908060020160029054906101000a900463ffffffff16908060020160069054906101000a900463ffffffff16905086565b6008600085815260200190815260200160002060020160009054906101000a900460ff16611541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153890613669565b60405180910390fd5b8261ffff166008600086815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1610156115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab906136d5565b60405180910390fd5b6000600a600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614611628576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161f90613741565b60405180910390fd5b600060086000868152602001908152602001600020600101548461ffff166116509190613761565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b88c9148600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016116d1919061240e565b602060405180830381865afa1580156116ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171291906135f0565b6fffffffffffffffffffffffffffffffff169050600082826117349190613237565b90506000600860008981526020019081526020016000206001015411156117995780341015611798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178f906137ef565b60405180910390fd5b5b6008600088815260200190815260200160002060020160019054906101000a900460ff16156118895760006117f9338989896040516020016117de94939291906138cf565b60405160208183030381529060405280519060200120612172565b90506118488186600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166121e49092919063ffffffff16565b611887576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187e90613969565b60405180910390fd5b505b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166319cb825f84600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896040518463ffffffff1660e01b815260040161190b929190613989565b60206040518083038185885af1158015611929573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061194e91906139c7565b905080600a600088815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555033600960008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600960008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000160146101000a81548161ffff021916908361ffff16021790555087600960008367ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600301819055507fc332ce7c560e1184b0358aa14014f7fbbbf083aa8611e28d4812bafb7b30861933888a84604051611a9c9493929190613a25565b60405180910390a15050505050505050565b611ab6611c82565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b285760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611b1f919061240e565b60405180910390fd5b611b3181612054565b50565b611b3c611c82565b6103e8611b4883612120565b14611b88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7f90613ab6565b60405180910390fd5b60005b8251811015611c4357600b6040518060600160405280858481518110611bb457611bb3612f8b565b5b60200260200101518152602001848481518110611bd457611bd3612f8b565b5b602002602001015181526020016103e8815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550508080611c3b9061326b565b915050611b8b565b505050565b600b8181548110611c5857600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b611c8a612118565b73ffffffffffffffffffffffffffffffffffffffff16611ca8610c70565b73ffffffffffffffffffffffffffffffffffffffff1614611d0757611ccb612118565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611cfe919061240e565b60405180910390fd5b565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f17c4cce12998322f805ff6c39786651b347a39141c4e8e47767fda085581cde33384600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684604051611d8a94939291906132b3565b60405180910390a1600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd3612118565b73ffffffffffffffffffffffffffffffffffffffff16148015611e4357508173ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990613b22565b60405180910390fd5b6000600960008567ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260000160149054906101000a900461ffff169050600080846002015460001c14611f38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f2f906133b0565b60405180910390fd5b8484600201819055506000611f548660001c8461ffff166106ea565b9050611f5f81612120565b915080856001019080519060200190611f799291906122ae565b50600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663731133e9856001856040518463ffffffff1660e01b8152600401611fda93929190613442565b600060405180830381600087803b158015611ff457600080fd5b505af1158015612008573d6000803e3d6000fd5b505050507f4573b1c4a81e563013c3bfa32c89bd049df6313564234d6a1c7c233a731f77fa848360018b604051612042949392919061348c565b60405180910390a15050505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b600080600090505b825181101561216c5782818151811061214457612143612f8b565b5b6020026020010151826121579190613237565b915080806121649061326b565b915050612128565b50919050565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509050600081846040516020016121c2929190613bb3565b6040516020818303038152906040528051906020012090508092505050919050565b60006121f08383612227565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490509392505050565b6000604182511461223757600080fd5b60008060006020850151915060408501519050606085015160001a9250600186848484604051600081526020016040526040516122779493929190613bf7565b6020604051602081039080840390855afa158015612299573d6000803e3d6000fd5b50505060206040510351935050505092915050565b8280548282559060005260206000209081019282156122ea579160200282015b828111156122e95782518255916020019190600101906122ce565b5b5090506122f791906122fb565b5090565b5b808211156123145760008160009055506001016122fc565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61233f8161232c565b811461234a57600080fd5b50565b60008135905061235c81612336565b92915050565b60006020828403121561237857612377612322565b5b60006123868482850161234d565b91505092915050565b600067ffffffffffffffff82169050919050565b6123ac8161238f565b82525050565b60006020820190506123c760008301846123a3565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123f8826123cd565b9050919050565b612408816123ed565b82525050565b600060208201905061242360008301846123ff565b92915050565b612432816123ed565b811461243d57600080fd5b50565b60008135905061244f81612429565b92915050565b60006020828403121561246b5761246a612322565b5b600061247984828501612440565b91505092915050565b61248b8161238f565b811461249657600080fd5b50565b6000813590506124a881612482565b92915050565b6000602082840312156124c4576124c3612322565b5b60006124d284828501612499565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61251a81612507565b82525050565b600061252c8383612511565b60208301905092915050565b6000602082019050919050565b6000612550826124db565b61255a81856124e6565b9350612565836124f7565b8060005b8381101561259657815161257d8882612520565b975061258883612538565b925050600181019050612569565b5085935050505092915050565b600060208201905081810360008301526125bd8184612545565b905092915050565b6125ce81612507565b81146125d957600080fd5b50565b6000813590506125eb816125c5565b92915050565b6000806040838503121561260857612607612322565b5b6000612616858286016125dc565b9250506020612627858286016125dc565b9150509250929050565b60008060006060848603121561264a57612649612322565b5b600061265886828701612499565b935050602061266986828701612440565b925050604061267a8682870161234d565b9150509250925092565b6000806040838503121561269b5761269a612322565b5b60006126a985828601612440565b92505060206126ba85828601612440565b9150509250929050565b6000602082840312156126da576126d9612322565b5b60006126e8848285016125dc565b91505092915050565b6126fa81612507565b82525050565b600060208201905061271560008301846126f1565b92915050565b6000806040838503121561273257612731612322565b5b600061274085828601612499565b92505060206127518582860161234d565b9150509250929050565b6000819050919050565b600061278061277b612776846123cd565b61275b565b6123cd565b9050919050565b600061279282612765565b9050919050565b60006127a482612787565b9050919050565b6127b481612799565b82525050565b60006020820190506127cf60008301846127ab565b92915050565b600063ffffffff82169050919050565b6127ee816127d5565b81146127f957600080fd5b50565b60008135905061280b816127e5565b92915050565b60008115159050919050565b61282681612811565b811461283157600080fd5b50565b6000813590506128438161281d565b92915050565b600080600080600060a0868803121561286557612864612322565b5b6000612873888289016125dc565b9550506020612884888289016127fc565b9450506040612895888289016125dc565b93505060606128a688828901612834565b92505060806128b788828901612834565b9150509295509295909350565b6000602082840312156128da576128d9612322565b5b60006128e884828501612834565b91505092915050565b600061ffff82169050919050565b612908816128f1565b82525050565b6129178161232c565b82525050565b600060808201905061293260008301876123ff565b61293f60208301866128ff565b61294c604083018561290e565b61295960608301846126f1565b95945050505050565b61296b816127d5565b82525050565b61297a81612811565b82525050565b600060c0820190506129956000830189612962565b6129a260208301886126f1565b6129af6040830187612971565b6129bc6060830186612971565b6129c96080830185612962565b6129d660a0830184612962565b979650505050505050565b6129ea816128f1565b81146129f557600080fd5b50565b600081359050612a07816129e1565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612a6082612a17565b810181811067ffffffffffffffff82111715612a7f57612a7e612a28565b5b80604052505050565b6000612a92612318565b9050612a9e8282612a57565b919050565b600067ffffffffffffffff821115612abe57612abd612a28565b5b612ac782612a17565b9050602081019050919050565b82818337600083830152505050565b6000612af6612af184612aa3565b612a88565b905082815260208101848484011115612b1257612b11612a12565b5b612b1d848285612ad4565b509392505050565b600082601f830112612b3a57612b39612a0d565b5b8135612b4a848260208601612ae3565b91505092915050565b60008060008060808587031215612b6d57612b6c612322565b5b6000612b7b878288016125dc565b9450506020612b8c878288016129f8565b9350506040612b9d8782880161234d565b925050606085013567ffffffffffffffff811115612bbe57612bbd612327565b5b612bca87828801612b25565b91505092959194509250565b600067ffffffffffffffff821115612bf157612bf0612a28565b5b602082029050602081019050919050565b600080fd5b6000612c1a612c1584612bd6565b612a88565b90508083825260208201905060208402830185811115612c3d57612c3c612c02565b5b835b81811015612c665780612c5288826125dc565b845260208401935050602081019050612c3f565b5050509392505050565b600082601f830112612c8557612c84612a0d565b5b8135612c95848260208601612c07565b91505092915050565b60008060408385031215612cb557612cb4612322565b5b600083013567ffffffffffffffff811115612cd357612cd2612327565b5b612cdf85828601612c70565b925050602083013567ffffffffffffffff811115612d0057612cff612327565b5b612d0c85828601612c70565b9150509250929050565b6000606082019050612d2b60008301866126f1565b612d3860208301856126f1565b612d4560408301846126f1565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115612dd357808604811115612daf57612dae612d4d565b5b6001851615612dbe5780820291505b8081029050612dcc85612d7c565b9450612d93565b94509492505050565b600082612dec5760019050612ea8565b81612dfa5760009050612ea8565b8160018114612e105760028114612e1a57612e49565b6001915050612ea8565b60ff841115612e2c57612e2b612d4d565b5b8360020a915084821115612e4357612e42612d4d565b5b50612ea8565b5060208310610133831016604e8410600b8410161715612e7e5782820a905083811115612e7957612e78612d4d565b5b612ea8565b612e8b8484846001612d89565b92509050818404811115612ea257612ea1612d4d565b5b81810290505b9392505050565b6000612eba82612507565b9150612ec5836128f1565b9250612ef27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612ddc565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612f3482612507565b9150612f3f83612507565b925082612f4f57612f4e612efa565b5b828204905092915050565b6000612f6582612507565b9150612f7083612507565b925082612f8057612f7f612efa565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000612fc5826128f1565b915061ffff8203612fd957612fd8612d4d565b5b600182019050919050565b600082825260208201905092915050565b7f4e6f7468696e6720746f20776974686472617700000000000000000000000000600082015250565b600061302b601383612fe4565b915061303682612ff5565b602082019050919050565b6000602082019050818103600083015261305a8161301e565b9050919050565b7f5472656173757279206973206e6f742073657400000000000000000000000000600082015250565b6000613097601383612fe4565b91506130a282613061565b602082019050919050565b600060208201905081810360008301526130c68161308a565b9050919050565b7f456e74726f70792061646472657373206e6f7420736574000000000000000000600082015250565b6000613103601783612fe4565b915061310e826130cd565b602082019050919050565b60006020820190508181036000830152613132816130f6565b9050919050565b7f4f6e6c7920456e74726f70792063616e2063616c6c20746869732066756e637460008201527f696f6e0000000000000000000000000000000000000000000000000000000000602082015250565b6000613195602383612fe4565b91506131a082613139565b604082019050919050565b600060208201905081810360008301526131c481613188565b9050919050565b7f4e4f545f414c4c4f5745445f5a45524f5f414444524553530000000000000000600082015250565b6000613201601883612fe4565b915061320c826131cb565b602082019050919050565b60006020820190508181036000830152613230816131f4565b9050919050565b600061324282612507565b915061324d83612507565b925082820190508082111561326557613264612d4d565b5b92915050565b600061327682612507565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036132a8576132a7612d4d565b5b600182019050919050565b60006080820190506132c860008301876123ff565b6132d560208301866123a3565b6132e260408301856123ff565b6132ef606083018461290e565b95945050505050565b7f43616c6c6572206973206e6f7420776f726b6572000000000000000000000000600082015250565b600061332e601483612fe4565b9150613339826132f8565b602082019050919050565b6000602082019050818103600083015261335d81613321565b9050919050565b7f4d696e742069732072657665616c656400000000000000000000000000000000600082015250565b600061339a601083612fe4565b91506133a582613364565b602082019050919050565b600060208201905081810360008301526133c98161338d565b9050919050565b6000819050919050565b60006133f56133f06133eb846133d0565b61275b565b612507565b9050919050565b613405816133da565b82525050565b600082825260208201905092915050565b50565b600061342c60008361340b565b91506134378261341c565b600082019050919050565b600060808201905061345760008301866123ff565b61346460208301856133fc565b61347160408301846126f1565b81810360608301526134828161341f565b9050949350505050565b60006080820190506134a160008301876123ff565b6134ae60208301866126f1565b6134bb60408301856133fc565b6134c860608301846123a3565b95945050505050565b7f676173466565206973206e6f7420736574000000000000000000000000000000600082015250565b6000613507601183612fe4565b9150613512826134d1565b602082019050919050565b60006020820190508181036000830152613536816134fa565b9050919050565b600060408201905061355260008301856123ff565b61355f60208301846123ff565b9392505050565b600081519050613575816125c5565b92915050565b60006020828403121561359157613590612322565b5b600061359f84828501613566565b91505092915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6135cd816135a8565b81146135d857600080fd5b50565b6000815190506135ea816135c4565b92915050565b60006020828403121561360657613605612322565b5b6000613614848285016135db565b91505092915050565b7f4d696e74207068617365206973206e6f7420617661696c61626c650000000000600082015250565b6000613653601b83612fe4565b915061365e8261361d565b602082019050919050565b6000602082019050818103600083015261368281613646565b9050919050565b7f4f766572206d6178207065722062617463680000000000000000000000000000600082015250565b60006136bf601283612fe4565b91506136ca82613689565b602082019050919050565b600060208201905081810360008301526136ee816136b2565b9050919050565b7f5261642069732075736564000000000000000000000000000000000000000000600082015250565b600061372b600b83612fe4565b9150613736826136f5565b602082019050919050565b6000602082019050818103600083015261375a8161371e565b9050919050565b600061376c82612507565b915061377783612507565b925082820261378581612507565b9150828204841483151761379c5761379b612d4d565b5b5092915050565b7f53656e64206d6f72652065746800000000000000000000000000000000000000600082015250565b60006137d9600d83612fe4565b91506137e4826137a3565b602082019050919050565b60006020820190508181036000830152613808816137cc565b9050919050565b60008160601b9050919050565b60006138278261380f565b9050919050565b60006138398261381c565b9050919050565b61385161384c826123ed565b61382e565b82525050565b6000819050919050565b61387261386d82612507565b613857565b82525050565b60008160f01b9050919050565b600061389082613878565b9050919050565b6138a86138a3826128f1565b613885565b82525050565b6000819050919050565b6138c96138c48261232c565b6138ae565b82525050565b60006138db8287613840565b6014820191506138eb8286613861565b6020820191506138fb8285613897565b60028201915061390b82846138b8565b60208201915081905095945050505050565b7f496e76616c6964207369676e6174757265000000000000000000000000000000600082015250565b6000613953601183612fe4565b915061395e8261391d565b602082019050919050565b6000602082019050818103600083015261398281613946565b9050919050565b600060408201905061399e60008301856123ff565b6139ab602083018461290e565b9392505050565b6000815190506139c181612482565b92915050565b6000602082840312156139dd576139dc612322565b5b60006139eb848285016139b2565b91505092915050565b6000613a0f613a0a613a05846128f1565b61275b565b612507565b9050919050565b613a1f816139f4565b82525050565b6000608082019050613a3a60008301876123ff565b613a476020830186613a16565b613a5460408301856126f1565b613a6160608301846123a3565b95945050505050565b7f496e76616c696420696e70757400000000000000000000000000000000000000600082015250565b6000613aa0600d83612fe4565b9150613aab82613a6a565b602082019050919050565b60006020820190508181036000830152613acf81613a93565b9050919050565b7f43616c6c6572206973206e6f7420656e74726f70790000000000000000000000600082015250565b6000613b0c601583612fe4565b9150613b1782613ad6565b602082019050919050565b60006020820190508181036000830152613b3b81613aff565b9050919050565b600081519050919050565b600081905092915050565b60005b83811015613b76578082015181840152602081019050613b5b565b60008484015250505050565b6000613b8d82613b42565b613b978185613b4d565b9350613ba7818560208601613b58565b80840191505092915050565b6000613bbf8285613b82565b9150613bcb82846138b8565b6020820191508190509392505050565b600060ff82169050919050565b613bf181613bdb565b82525050565b6000608082019050613c0c600083018761290e565b613c196020830186613be8565b613c26604083018561290e565b613c33606083018461290e565b9594505050505056fea2646970667358221220977349813f9c4bd294b1a932fd9598a0c8f140239a5bc03a0060c7a541da729c64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007866ac3933dca99b2e9a80f8948344a387a7bf620000000000000000000000003b920eb71418fb4a4e752b8c728caea582759057000000000000000000000000ec6d0c755c255f2ecb400f716a557270cead7d8f
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x7866Ac3933dCA99b2e9a80F8948344a387a7BF62
Arg [1] : _gangster (address): 0x3B920eb71418FB4A4E752B8C728caeA582759057
Arg [2] : _signer (address): 0xEc6D0c755C255f2eCB400F716a557270cEAd7D8F
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000007866ac3933dca99b2e9a80f8948344a387a7bf62
Arg [1] : 0000000000000000000000003b920eb71418fb4a4e752b8c728caea582759057
Arg [2] : 000000000000000000000000ec6d0c755c255f2ecb400f716a557270cead7d8f
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.