Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 163 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint Free Pack | 16305186 | 1161 days ago | IN | 0 ETH | 0.00308349 | ||||
| Mint Free Pack | 16236613 | 1171 days ago | IN | 0 ETH | 0.00328678 | ||||
| Mint Free Pack | 16235860 | 1171 days ago | IN | 0 ETH | 0.00295331 | ||||
| Mint Free Pack | 16233021 | 1171 days ago | IN | 0 ETH | 0.0031505 | ||||
| Mint Free Pack | 16230919 | 1171 days ago | IN | 0 ETH | 0.00351374 | ||||
| Mint Free Pack | 16230455 | 1171 days ago | IN | 0 ETH | 0.00300845 | ||||
| Mint Free Pack | 16225731 | 1172 days ago | IN | 0 ETH | 0.00192386 | ||||
| Mint Free Pack | 16225467 | 1172 days ago | IN | 0 ETH | 0.0029809 | ||||
| Mint Free Pack | 16225461 | 1172 days ago | IN | 0 ETH | 0.00299631 | ||||
| Mint Free Pack | 16225303 | 1172 days ago | IN | 0 ETH | 0.00231615 | ||||
| Mint Free Pack | 16225301 | 1172 days ago | IN | 0 ETH | 0.00282659 | ||||
| Mint Free Pack | 16225273 | 1172 days ago | IN | 0 ETH | 0.00184869 | ||||
| Mint Free Pack | 16225268 | 1172 days ago | IN | 0 ETH | 0.00255027 | ||||
| Mint Free Pack | 16225265 | 1172 days ago | IN | 0 ETH | 0.00311092 | ||||
| Mint Free Pack | 16225243 | 1172 days ago | IN | 0 ETH | 0.00288056 | ||||
| Mint Free Pack | 16225187 | 1172 days ago | IN | 0 ETH | 0.00244725 | ||||
| Mint Free Pack | 16225048 | 1172 days ago | IN | 0 ETH | 0.00272991 | ||||
| Mint Free Pack | 16225025 | 1172 days ago | IN | 0 ETH | 0.00055973 | ||||
| Mint Free Pack | 16225024 | 1172 days ago | IN | 0 ETH | 0.00056589 | ||||
| Mint Free Pack | 16225020 | 1172 days ago | IN | 0 ETH | 0.00275713 | ||||
| Mint Free Pack | 16225019 | 1172 days ago | IN | 0 ETH | 0.00270341 | ||||
| Mint Free Pack | 16225018 | 1172 days ago | IN | 0 ETH | 0.00279728 | ||||
| Mint Free Pack | 16225004 | 1172 days ago | IN | 0 ETH | 0.00286129 | ||||
| Mint Free Pack | 16224964 | 1172 days ago | IN | 0 ETH | 0.00282422 | ||||
| Mint Free Pack | 16224956 | 1172 days ago | IN | 0 ETH | 0.00282151 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AltariusMinter
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 2500 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./AltariusCards.sol";
import "./AltariusMinterStorage.sol";
contract AltariusMinter is VRFConsumerBaseV2, AccessControl, Pausable {
struct RequestStatus {
address sender;
bool exists;
bool fulfilled;
bool minted;
uint256 randomWord;
uint256 edition;
}
bytes32 public constant CONFIGURATOR_ROLE = keccak256("CONFIGURATOR_ROLE");
bytes32 public constant WITHDRAWER_ROLE = keccak256("WITHDRAWER_ROLE");
mapping(uint256 => RequestStatus) public vrfRequests; // requestId => requestStatus
mapping(address => uint256) public pendingVrfRequestIds; // sender => requestId
bytes32 public vrfKeyHash;
uint64 public vrfSubscriptionId;
uint32 public vrfCallbackGasLimit;
uint16 public vrfRequestConfirmations;
AltariusCards public altariusCards;
AltariusMinterStorage public s;
VRFCoordinatorV2Interface public vrfCoordinator;
event RequestSent(address indexed sender, uint256 indexed requestId);
event RequestFulfilled(
address indexed sender,
uint256 indexed requestId,
uint256 randomWord
);
event PackMinted(address indexed minter, uint256 edition, uint256[] ids);
constructor(
AltariusCards _altariusCards,
AltariusMinterStorage _altariusMinterStorage,
address _vrfCoordinator,
bytes32 _vrfKeyHash,
uint64 _vrfSubscriptionId,
uint32 _vrfCallbackGasLimit,
uint16 _vrfRequestConfirmations
) VRFConsumerBaseV2(_vrfCoordinator) {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
altariusCards = _altariusCards;
s = _altariusMinterStorage;
vrfCoordinator = VRFCoordinatorV2Interface(_vrfCoordinator);
vrfKeyHash = _vrfKeyHash;
vrfSubscriptionId = _vrfSubscriptionId;
vrfCallbackGasLimit = _vrfCallbackGasLimit;
vrfRequestConfirmations = _vrfRequestConfirmations;
}
receive() external payable {}
function withdraw(uint256 amount) external onlyRole(WITHDRAWER_ROLE) {
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
}
function pause() external onlyRole(CONFIGURATOR_ROLE) {
_pause();
}
function unpause() external onlyRole(CONFIGURATOR_ROLE) {
_unpause();
}
function setVrfCoordinator(
address _vrfCoordinator
) external onlyRole(CONFIGURATOR_ROLE) {
vrfCoordinator = VRFCoordinatorV2Interface(_vrfCoordinator);
}
function setVrfKeyHash(
bytes32 _vrfKeyHash
) external onlyRole(CONFIGURATOR_ROLE) {
vrfKeyHash = _vrfKeyHash;
}
function setVrfSubscriptionId(
uint64 _vrfSubscriptionId
) external onlyRole(CONFIGURATOR_ROLE) {
vrfSubscriptionId = _vrfSubscriptionId;
}
function setCallbackGasLimit(
uint32 _callbackGasLimit
) external onlyRole(CONFIGURATOR_ROLE) {
vrfCallbackGasLimit = _callbackGasLimit;
}
function setRequestConfirmations(
uint16 _requestConfirmations
) external onlyRole(CONFIGURATOR_ROLE) {
vrfRequestConfirmations = _requestConfirmations;
}
function mintFreePack(
uint256 edition,
bytes32[] memory proof
) external whenNotPaused {
AltariusMinterStorage.PackMetadata memory packMetadata = s
.getPackMetadata(edition);
uint256 freePacksClaimed = s.getFreePacksClaimed(edition, msg.sender);
require(!packMetadata.paused, "Pack paused");
require(packMetadata.freePacksAvailable > 0, "No free packs left");
require(
freePacksClaimed < packMetadata.maxFreePacksPerAddress,
"Max free packs minted"
);
if (packMetadata.onlyWhitelisted) {
bytes32 leaf = keccak256(
bytes.concat(keccak256(abi.encode(msg.sender)))
);
require(
MerkleProof.verify(proof, packMetadata.merkleRoot, leaf),
"Invalid proof"
);
}
s.setFreePacksAvailable(edition, packMetadata.freePacksAvailable - 1);
s.setFreePacksClaimed(edition, msg.sender, freePacksClaimed + 1);
uint256 random = uint256(
keccak256(
abi.encodePacked(
msg.sender,
block.coinbase,
block.difficulty,
block.gaslimit,
block.timestamp
)
)
);
mintPack(edition, random);
}
function requestPack(
uint256 edition,
bytes32[] memory proof
) external payable whenNotPaused returns (uint256 requestId) {
AltariusMinterStorage.PackMetadata memory packMetadata = s
.getPackMetadata(edition);
require(!packMetadata.paused, "Pack paused");
require(packMetadata.payablePacksAvailable > 0, "No packs left");
require(msg.value == packMetadata.price, "Incorrect amount");
require(
pendingVrfRequestIds[msg.sender] == 0,
"Request already pending"
);
if (packMetadata.onlyWhitelisted) {
bytes32 leaf = keccak256(
bytes.concat(keccak256(abi.encode(msg.sender)))
);
require(
MerkleProof.verify(proof, packMetadata.merkleRoot, leaf),
"Invalid proof"
);
}
s.setPayablePacksAvailable(edition, packMetadata.payablePacksAvailable - 1);
requestId = vrfCoordinator.requestRandomWords(
vrfKeyHash,
vrfSubscriptionId,
vrfRequestConfirmations,
vrfCallbackGasLimit,
1
);
vrfRequests[requestId] = RequestStatus({
sender: msg.sender,
exists: true,
fulfilled: false,
minted: false,
randomWord: 0,
edition: edition
});
pendingVrfRequestIds[msg.sender] = requestId;
emit RequestSent(msg.sender, requestId);
return requestId;
}
function mintPayablePack() external whenNotPaused {
require(pendingVrfRequestIds[msg.sender] != 0, "No pending request");
uint256 requestId = pendingVrfRequestIds[msg.sender];
RequestStatus memory request = vrfRequests[requestId];
require(request.fulfilled, "Request not fulfilled");
request.minted = true;
pendingVrfRequestIds[msg.sender] = 0;
mintPack(request.edition, request.randomWord);
}
function getPackMetadata(
uint256 edition
) external view returns (AltariusMinterStorage.PackMetadata memory) {
return s.getPackMetadata(edition);
}
function getFreePacksClaimed(
uint256 edition,
address user
) external view returns (uint256) {
return s.getFreePacksClaimed(edition, user);
}
function getCardIds(
uint256 edition,
uint256 cardType,
uint256 level,
uint256 rarity,
bool holographic
) external view returns (uint256[] memory) {
return s.getCardIds(edition, cardType, level, rarity, holographic);
}
function getPackMerkleTreeCid(
uint256 edition
) external view returns (string memory) {
return s.getPackMerkleTreeCid(edition);
}
function fulfillRandomWords(
uint256 _requestId,
uint256[] memory _randomWords
) internal override {
require(vrfRequests[_requestId].exists, "request not found");
vrfRequests[_requestId].fulfilled = true;
vrfRequests[_requestId].randomWord = _randomWords[0];
emit RequestFulfilled(
vrfRequests[_requestId].sender,
_requestId,
_randomWords[0]
);
}
function mintPack(uint256 edition, uint256 random) internal {
uint256[] memory mintableCardIds = new uint256[](3);
uint256[] memory randomWords = expand(random, 12);
// Armor
mintableCardIds[0] = getRandomCard(
edition,
0,
randomWords[0],
randomWords[1],
randomWords[2],
randomWords[3]
);
// Hero
mintableCardIds[1] = getRandomCard(
edition,
1,
randomWords[4],
randomWords[5],
randomWords[6],
randomWords[7]
);
// Weapon
mintableCardIds[2] = getRandomCard(
edition,
2,
randomWords[8],
randomWords[9],
randomWords[10],
randomWords[11]
);
uint256[] memory mintableCardAmounts = new uint256[](3);
mintableCardAmounts[0] = 1;
mintableCardAmounts[1] = 1;
mintableCardAmounts[2] = 1;
altariusCards.mintBatch(
msg.sender,
mintableCardIds,
mintableCardAmounts,
""
);
emit PackMinted(msg.sender, edition, mintableCardIds);
}
function getRandomCard(
uint256 edition,
uint256 cardType,
uint256 randomWordLevel,
uint256 randomWordRarity,
uint256 randomWordHolographic,
uint256 randomWordCard
) internal view returns (uint256) {
uint256 level = getRandomLevel(randomWordLevel);
uint256 rarity = getRandomRarity(randomWordRarity);
bool holographic = getRandomHolographic(randomWordHolographic);
if (
s
.getCardIds(edition, cardType, level, rarity, holographic)
.length == 0
) {
holographic = false;
}
uint256[] memory randomCardIds = s.getCardIds(
edition,
cardType,
level,
rarity,
holographic
);
return randomCardIds[randomWordCard % randomCardIds.length];
}
function getRandomLevel(uint256 n) internal pure returns (uint256) {
uint256 probability = n % 10000;
if (probability < 7395) {
return 1;
} else if (probability < 9945) {
return 2;
} else if (probability < 9995) {
return 3;
} else {
return 4;
}
}
function getRandomRarity(uint256 n) internal pure returns (uint256) {
uint256 probability = n % 10000;
if (probability < 4800) {
return 0;
} else if (probability < 7300) {
return 1;
} else if (probability < 9400) {
return 2;
} else {
return 3;
}
}
function getRandomHolographic(uint256 n) internal pure returns (bool) {
return n % 100 == 1;
}
function expand(
uint256 randomValue,
uint256 n
) internal pure returns (uint256[] memory expandedValues) {
expandedValues = new uint256[](n);
for (uint256 i = 0; i < n; i++) {
expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
}
return expandedValues;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface VRFCoordinatorV2Interface {
/**
* @notice Get configuration relevant for making requests
* @return minimumRequestConfirmations global min for request confirmations
* @return maxGasLimit global max for request gas limit
* @return s_provingKeyHashes list of registered key hashes
*/
function getRequestConfig()
external
view
returns (
uint16,
uint32,
bytes32[] memory
);
/**
* @notice Request a set of random words.
* @param keyHash - Corresponds to a particular oracle job which uses
* that key for generating the VRF proof. Different keyHash's have different gas price
* ceilings, so you can select a specific one to bound your maximum per request cost.
* @param subId - The ID of the VRF subscription. Must be funded
* with the minimum subscription balance required for the selected keyHash.
* @param minimumRequestConfirmations - How many blocks you'd like the
* oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
* for why you may want to request more. The acceptable range is
* [minimumRequestBlockConfirmations, 200].
* @param callbackGasLimit - How much gas you'd like to receive in your
* fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
* may be slightly less than this amount because of gas used calling the function
* (argument decoding etc.), so you may need to request slightly more than you expect
* to have inside fulfillRandomWords. The acceptable range is
* [0, maxGasLimit]
* @param numWords - The number of uint256 random values you'd like to receive
* in your fulfillRandomWords callback. Note these numbers are expanded in a
* secure way by the VRFCoordinator from a single random value supplied by the oracle.
* @return requestId - A unique identifier of the request. Can be used to match
* a request to a response in fulfillRandomWords.
*/
function requestRandomWords(
bytes32 keyHash,
uint64 subId,
uint16 minimumRequestConfirmations,
uint32 callbackGasLimit,
uint32 numWords
) external returns (uint256 requestId);
/**
* @notice Create a VRF subscription.
* @return subId - A unique subscription id.
* @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
* @dev Note to fund the subscription, use transferAndCall. For example
* @dev LINKTOKEN.transferAndCall(
* @dev address(COORDINATOR),
* @dev amount,
* @dev abi.encode(subId));
*/
function createSubscription() external returns (uint64 subId);
/**
* @notice Get a VRF subscription.
* @param subId - ID of the subscription
* @return balance - LINK balance of the subscription in juels.
* @return reqCount - number of requests for this subscription, determines fee tier.
* @return owner - owner of the subscription.
* @return consumers - list of consumer address which are able to use this subscription.
*/
function getSubscription(uint64 subId)
external
view
returns (
uint96 balance,
uint64 reqCount,
address owner,
address[] memory consumers
);
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @param newOwner - proposed new owner of the subscription
*/
function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @dev will revert if original owner of subId has
* not requested that msg.sender become the new owner.
*/
function acceptSubscriptionOwnerTransfer(uint64 subId) external;
/**
* @notice Add a consumer to a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - New consumer which can use the subscription
*/
function addConsumer(uint64 subId, address consumer) external;
/**
* @notice Remove a consumer from a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - Consumer to remove from the subscription
*/
function removeConsumer(uint64 subId, address consumer) external;
/**
* @notice Cancel a subscription
* @param subId - ID of the subscription
* @param to - Where to send the remaining LINK to
*/
function cancelSubscription(uint64 subId, address to) external;
/*
* @notice Check to see if there exists a request commitment consumers
* for all consumers and keyhashes for a given sub.
* @param subId - ID of the subscription
* @return true if there exists at least one unfulfilled request for the subscription, false
* otherwise.
*/
function pendingRequestExists(uint64 subId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness. It ensures 2 things:
* @dev 1. The fulfillment came from the VRFCoordinator
* @dev 2. The consumer contract implements fulfillRandomWords.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constructor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash). Create subscription, fund it
* @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
* @dev subscription management functions).
* @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
* @dev callbackGasLimit, numWords),
* @dev see (VRFCoordinatorInterface for a description of the arguments).
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomWords method.
*
* @dev The randomness argument to fulfillRandomWords is a set of random words
* @dev generated from your requestId and the blockHash of the request.
*
* @dev If your contract could have concurrent requests open, you can use the
* @dev requestId returned from requestRandomWords to track which response is associated
* @dev with which randomness request.
* @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ.
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request. It is for this reason that
* @dev that you can signal to an oracle you'd like them to wait longer before
* @dev responding to the request (however this is not enforced in the contract
* @dev and so remains effective only in the case of unmodified oracle software).
*/
abstract contract VRFConsumerBaseV2 {
error OnlyCoordinatorCanFulfill(address have, address want);
address private immutable vrfCoordinator;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
*/
constructor(address _vrfCoordinator) {
vrfCoordinator = _vrfCoordinator;
}
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomWords the VRF output expanded to the requested number of words
*/
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
if (msg.sender != vrfCoordinator) {
revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
}
fulfillRandomWords(requestId, randomWords);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../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:
*
* ```
* 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}:
*
* ```
* 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.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
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 override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @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 override 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 override 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 override 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 `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @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 Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @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.
*
* _Available since v3.1._
*/
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 `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.0;
import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./extensions/IERC1155MetadataURI.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/ERC165.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
*
* _Available since v3.1._
*/
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
using Address for address;
// Mapping from token ID to account balances
mapping(uint256 => mapping(address => uint256)) private _balances;
// Mapping from account to operator approvals
mapping(address => mapping(address => 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) public view virtual override returns (string memory) {
return _uri;
}
/**
* @dev See {IERC1155-balanceOf}.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: address zero is not a valid owner");
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
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner or approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner or approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
/**
* @dev Transfers `amount` 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 `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 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, 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.
*/
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
emit TransferBatch(operator, from, to, ids, amounts);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, 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 amounts 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 `amount` tokens of token 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 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - 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 amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
_balances[ids[i]][to] += amounts[i];
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
/**
* @dev Destroys `amount` tokens of token type `id` from `from`
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `amount` tokens of token type `id`.
*/
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
*/
function _burnBatch(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `ids` and `amounts` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `id` and `amount` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non-ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non-ERC1155Receiver implementer");
}
}
}
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/extensions/ERC1155Burnable.sol)
pragma solidity ^0.8.0;
import "../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.
*
* _Available since v3.1._
*/
abstract contract ERC1155Burnable is ERC1155 {
function burn(
address account,
uint256 id,
uint256 value
) public virtual {
require(
account == _msgSender() || isApprovedForAll(account, _msgSender()),
"ERC1155: caller is not token owner or approved"
);
_burn(account, id, value);
}
function burnBatch(
address account,
uint256[] memory ids,
uint256[] memory values
) public virtual {
require(
account == _msgSender() || isApprovedForAll(account, _msgSender()),
"ERC1155: caller is not token owner or approved"
);
_burnBatch(account, ids, values);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)
pragma solidity ^0.8.0;
import "../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.
*/
abstract contract ERC1155Supply is ERC1155 {
mapping(uint256 => uint256) private _totalSupply;
/**
* @dev Total amount of tokens in with a given id.
*/
function totalSupply(uint256 id) public view virtual returns (uint256) {
return _totalSupply[id];
}
/**
* @dev Indicates whether any token exist with a given id, or not.
*/
function exists(uint256 id) public view virtual returns (bool) {
return ERC1155Supply.totalSupply(id) > 0;
}
/**
* @dev See {ERC1155-_beforeTokenTransfer}.
*/
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual override {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
if (from == address(0)) {
for (uint256 i = 0; i < ids.length; ++i) {
_totalSupply[ids[i]] += amounts[i];
}
}
if (to == address(0)) {
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 supply = _totalSupply[id];
require(supply >= amount, "ERC1155: burn amount exceeds totalSupply");
unchecked {
_totalSupply[id] = supply - amount;
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.0;
import "../IERC1155.sol";
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
*
* _Available since v3.1._
*/
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 v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token 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 amount 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 `amount` tokens of token type `id` from `from` to `to`.
*
* 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 `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 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` 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 amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
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 v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*
* _Available since v4.7._
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* _Available since v4.7._
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./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);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @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 v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @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 up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (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; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 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.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
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 (rounding == Rounding.Up && 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 down.
*
* 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* 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 + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* 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 10, 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 + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
import "./AltariusMetadata.sol";
/**
* @title Altarius Cards
*
* @dev This contract holds the Altarius cards tokens using an ERC1155 implementation.
* Metadata is stored in the AltariusMetadata contract.
*/
contract AltariusCards is
ERC1155,
ERC1155Burnable,
AccessControl,
ERC1155Supply
{
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
AltariusMetadata public altariusMetadata;
constructor(AltariusMetadata _altariusMetadata) ERC1155("") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
altariusMetadata = _altariusMetadata;
}
function mint(
address account,
uint256 id,
uint256 amount,
bytes memory data
) external onlyRole(MINTER_ROLE) {
_mint(account, id, amount, data);
}
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) external onlyRole(MINTER_ROLE) {
_mintBatch(to, ids, amounts, data);
}
function metadata(
uint256 id
) external view returns (AltariusMetadata.Metadata memory) {
return altariusMetadata.getMetadata(id);
}
function name(uint256 id) external view returns (bytes32) {
return altariusMetadata.getName(id);
}
function images(
uint256 id
) external view returns (AltariusMetadata.Images memory) {
return altariusMetadata.getImages(id);
}
function metadataLength() external view returns (uint256) {
return altariusMetadata.getMetadataLength();
}
function uri(uint256 id) public view override returns (string memory) {
return altariusMetadata.uri(id);
}
function supportsInterface(
bytes4 interfaceId
) public view override(ERC1155, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal override(ERC1155, ERC1155Supply) {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./libs/Base64.sol";
/**
* @title Altarius Metadata
*
* @dev This contract stores the metadata of the Altarius cards.
* Metadata is stored on-chain, except for images. Only IPFS CID is stored for them.
*
* Full metadata is divided into 3 parts:
* - Name: Stores the name of the card.
* - Metadata: Stores card metadata to be used by other contracts.
* - Images: Stores the IPFS CID of the images of the card.
*
* Type, rarity and edition strings are linked to their respective mappings for efficiency.
*/
contract AltariusMetadata is AccessControl {
using Counters for Counters.Counter;
struct Metadata {
bool immortal;
bool borderless;
bool holographic;
uint40 level;
uint24 cardType;
uint24 rarity;
uint24 edition;
uint24 moon;
uint24 sun;
uint24 swift;
uint24 strong;
uint24 sorcerous;
}
struct Images {
bytes32 highCid1;
bytes32 highCid2;
bytes32 thumbnailCid1;
bytes32 thumbnailCid2;
bytes32 squareCid1;
bytes32 squareCid2;
}
bytes32 public constant CREATOR_ROLE = keccak256("CREATOR_ROLE");
mapping(uint256 => bytes32) public cardTypes;
Counters.Counter public cardTypeCounter;
mapping(uint256 => bytes32) public rarities;
Counters.Counter public rarityCounter;
mapping(uint256 => bytes32) public editions;
Counters.Counter public editionCounter;
mapping(uint256 => Metadata) public tokensMetadata;
mapping(uint256 => bytes32) public tokensName;
mapping(uint256 => Images) public tokensImages;
Counters.Counter public tokensMetadataCounter;
event MetadataCreated(uint256 indexed id);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function createCardType(bytes32 name) external onlyRole(CREATOR_ROLE) {
cardTypes[cardTypeCounter.current()] = name;
cardTypeCounter.increment();
}
function createRarity(bytes32 name) external onlyRole(CREATOR_ROLE) {
rarities[rarityCounter.current()] = name;
rarityCounter.increment();
}
function createEdition(bytes32 name) external onlyRole(CREATOR_ROLE) {
editions[editionCounter.current()] = name;
editionCounter.increment();
}
function createMetadata(
uint256 id,
Metadata calldata metadata,
bytes32 name,
Images calldata images
) external onlyRole(CREATOR_ROLE) {
tokensMetadataCounter.increment();
require(id == tokensMetadataCounter.current(), "Invalid id");
tokensMetadata[id] = metadata;
tokensName[id] = name;
tokensImages[id] = images;
emit MetadataCreated(id);
}
function getMetadata(
uint256 id
) external view returns (AltariusMetadata.Metadata memory) {
return tokensMetadata[id];
}
function getName(uint256 id) external view returns (bytes32) {
return tokensName[id];
}
function getImages(
uint256 id
) external view returns (AltariusMetadata.Images memory) {
return tokensImages[id];
}
function getMetadataLength() external view returns (uint256) {
return tokensMetadataCounter.current();
}
function uri(uint256 id) external view returns (string memory) {
Metadata memory metadata = tokensMetadata[id];
bytes32 name = tokensName[id];
Images memory images = tokensImages[id];
require(name.length > 0, "Metadata not found");
return _metadataUri(metadata, name, images);
}
function _metadataUri(
Metadata memory metadata,
bytes32 name,
Images memory images
) private view returns (string memory) {
string memory json = Base64.encode(
bytes(
string.concat(
'{"name":"',
_bytes32ToString(name),
'","image": "ipfs://',
string.concat(
_bytes32ToString(images.highCid1),
_bytes32ToString(images.highCid2)
),
'","thumbnail": "ipfs://',
string.concat(
_bytes32ToString(images.thumbnailCid1),
_bytes32ToString(images.thumbnailCid2)
),
'","square": "ipfs://',
string.concat(
_bytes32ToString(images.squareCid1),
_bytes32ToString(images.squareCid2)
),
'",',
_attributesUri(metadata),
"}"
)
)
);
return string.concat("data:application/json;base64,", json);
}
function _attributesUri(
Metadata memory metadata
) private view returns (string memory) {
return
string.concat(
'"attributes": [',
_attributeUri(
"Type",
_bytes32ToString(cardTypes[metadata.cardType]),
true,
true
),
_attributeUri(
"Level",
Strings.toString(metadata.level),
false,
true
),
_attributeUri(
"Rarity",
_bytes32ToString(rarities[metadata.rarity]),
true,
true
),
_attributeUri(
"Edition",
_bytes32ToString(editions[metadata.edition]),
true,
true
),
_attributeUri(
"Immortal",
metadata.immortal ? "true" : "false",
false,
true
),
_attributeUri(
"Borderless",
metadata.borderless ? "true" : "false",
false,
true
),
_attributeUri(
"Holographic",
metadata.holographic ? "true" : "false",
false,
true
),
_pipsUri(metadata),
"]"
);
}
function _pipsUri(
Metadata memory metadata
) private pure returns (string memory) {
return
string.concat(
_attributeUri(
"Moon",
Strings.toString(metadata.moon),
false,
true
),
_attributeUri(
"Sun",
Strings.toString(metadata.sun),
false,
true
),
_attributeUri(
"Swift",
Strings.toString(metadata.swift),
false,
true
),
_attributeUri(
"Strong",
Strings.toString(metadata.strong),
false,
true
),
_attributeUri(
"Sorcerous",
Strings.toString(metadata.sorcerous),
false,
false
)
);
}
function _attributeUri(
string memory traitType,
string memory value,
bool isString,
bool trailingComma
) private pure returns (string memory) {
return
string.concat(
'{"trait_type": "',
traitType,
'", "value": ',
isString ? string.concat('"', value, '"') : value,
"}",
trailingComma ? "," : ""
);
}
function _bytes32ToString(
bytes32 data
) private pure returns (string memory) {
uint i = 0;
while (i < 32 && uint8(data[i]) != 0) {
++i;
}
bytes memory result = new bytes(i);
i = 0;
while (i < 32 && data[i] != 0) {
result[i] = data[i];
++i;
}
return string(result);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract AltariusMinterStorage is AccessControl {
struct PackMetadata {
uint256 price;
uint104 freePacksAvailable;
uint104 payablePacksAvailable;
uint24 maxFreePacksPerAddress;
bool freePacksEnabled;
bool onlyWhitelisted;
bool paused;
bytes32 merkleRoot;
bytes32 merkleTreeCid1;
bytes32 merkleTreeCid2;
}
bytes32 public constant CONFIGURATOR_ROLE = keccak256("CONFIGURATOR_ROLE");
mapping(uint256 => PackMetadata) public packsMetadata; // edition => PackMetadata
mapping(uint256 => mapping(address => uint256))
public freePacksClaimedPerEdition; // edition => claimer => amount
mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(bool => uint256[])))))
public cardIds; // edition => type => level => rarity => holographic => cardIds
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function setPackPrice(
uint256 edition,
uint256 price
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].price = price;
}
function setFreePacksAvailable(
uint256 edition,
uint104 freePacksAvailable
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].freePacksAvailable = freePacksAvailable;
}
function setPayablePacksAvailable(
uint256 edition,
uint104 payablePacksAvailable
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].payablePacksAvailable = payablePacksAvailable;
}
function setMaxFreePacksPerAddress(
uint256 edition,
uint24 maxFreePacksPerAddress
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].maxFreePacksPerAddress = maxFreePacksPerAddress;
}
function setFreePacksEnabled(
uint256 edition,
bool freePacksEnabled
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].freePacksEnabled = freePacksEnabled;
}
function setPackOnlyWhitelisted(
uint256 edition,
bool onlyWhitelisted
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].onlyWhitelisted = onlyWhitelisted;
}
function setPackPaused(
uint256 edition,
bool paused
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].paused = paused;
}
function setFreePacksClaimed(
uint256 edition,
address claimer,
uint256 amount
) external onlyRole(CONFIGURATOR_ROLE) {
freePacksClaimedPerEdition[edition][claimer] = amount;
}
function setCardIds(
uint256 edition,
uint256 cardType,
uint256 level,
uint256 rarity,
bool holographic,
uint256[] memory _cardIds
) external onlyRole(CONFIGURATOR_ROLE) {
cardIds[edition][cardType][level][rarity][holographic] = _cardIds;
}
function setPackMerkle(
uint256 edition,
bytes32 root,
bytes32 treeCid1,
bytes32 treeCid2
) external onlyRole(CONFIGURATOR_ROLE) {
packsMetadata[edition].merkleRoot = root;
packsMetadata[edition].merkleTreeCid1 = treeCid1;
packsMetadata[edition].merkleTreeCid2 = treeCid2;
}
function getPackMetadata(
uint256 edition
) external view returns (PackMetadata memory) {
return packsMetadata[edition];
}
function getFreePacksClaimed(
uint256 edition,
address claimer
) external view returns (uint256) {
return freePacksClaimedPerEdition[edition][claimer];
}
function getCardIds(
uint256 edition,
uint256 cardType,
uint256 level,
uint256 rarity,
bool holographic
) external view returns (uint256[] memory) {
return cardIds[edition][cardType][level][rarity][holographic];
}
function getPackMerkleTreeCid(
uint256 edition
) external view returns (string memory) {
return
string.concat(
_bytes32ToString(packsMetadata[edition].merkleTreeCid1),
_bytes32ToString(packsMetadata[edition].merkleTreeCid2)
);
}
function _bytes32ToString(
bytes32 data
) private pure returns (string memory) {
uint i = 0;
while (i < 32 && uint8(data[i]) != 0) {
++i;
}
bytes memory result = new bytes(i);
i = 0;
while (i < 32 && data[i] != 0) {
result[i] = data[i];
++i;
}
return string(result);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides a set of functions to operate with Base64 strings.
*
* _Available since v4.5._
*/
library Base64 {
/**
* @dev Base64 Encoding/Decoding Table
*/
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/
function encode(bytes memory data) internal pure returns (string memory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/
if (data.length == 0) return "";
// Loads the table into memory
string memory table = _TABLE;
// Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
// and split into 4 numbers of 6 bits.
// The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
// - `data.length + 2` -> Round up
// - `/ 3` -> Number of 3-bytes chunks
// - `4 *` -> 4 characters for each chunk
string memory result = new string(4 * ((data.length + 2) / 3));
/// @solidity memory-safe-assembly
assembly {
// Prepare the lookup table (skip the first "length" byte)
let tablePtr := add(table, 1)
// Prepare result pointer, jump over length
let resultPtr := add(result, 32)
// Run over the input, 3 bytes at a time
for {
let dataPtr := data
let endPtr := add(data, mload(data))
} lt(dataPtr, endPtr) {
} {
// Advance 3 bytes
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
// To write each character, shift the 3 bytes (18 bits) chunk
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
// and apply logical AND with 0x3F which is the number of
// the previous character in the ASCII table prior to the Base64 Table
// The result is then added to the table to get the character to write,
// and finally write it in the result pointer but with a left shift
// of 256 (1 byte) - 8 (1 ASCII char) = 248 bits
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
}
// When data `bytes` is not exactly 3 bytes long
// it is padded with `=` characters at the end
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
return result;
}
}{
"optimizer": {
"enabled": true,
"runs": 2500
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract AltariusCards","name":"_altariusCards","type":"address"},{"internalType":"contract AltariusMinterStorage","name":"_altariusMinterStorage","type":"address"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"bytes32","name":"_vrfKeyHash","type":"bytes32"},{"internalType":"uint64","name":"_vrfSubscriptionId","type":"uint64"},{"internalType":"uint32","name":"_vrfCallbackGasLimit","type":"uint32"},{"internalType":"uint16","name":"_vrfRequestConfirmations","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"edition","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"PackMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomWord","type":"uint256"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"RequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"CONFIGURATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"altariusCards","outputs":[{"internalType":"contract AltariusCards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"},{"internalType":"uint256","name":"cardType","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"rarity","type":"uint256"},{"internalType":"bool","name":"holographic","type":"bool"}],"name":"getCardIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getFreePacksClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"}],"name":"getPackMerkleTreeCid","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"}],"name":"getPackMetadata","outputs":[{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint104","name":"freePacksAvailable","type":"uint104"},{"internalType":"uint104","name":"payablePacksAvailable","type":"uint104"},{"internalType":"uint24","name":"maxFreePacksPerAddress","type":"uint24"},{"internalType":"bool","name":"freePacksEnabled","type":"bool"},{"internalType":"bool","name":"onlyWhitelisted","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"merkleTreeCid1","type":"bytes32"},{"internalType":"bytes32","name":"merkleTreeCid2","type":"bytes32"}],"internalType":"struct AltariusMinterStorage.PackMetadata","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"mintFreePack","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintPayablePack","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingVrfRequestIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"edition","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"requestPack","outputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"s","outputs":[{"internalType":"contract AltariusMinterStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"setCallbackGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_requestConfirmations","type":"uint16"}],"name":"setRequestConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vrfCoordinator","type":"address"}],"name":"setVrfCoordinator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_vrfKeyHash","type":"bytes32"}],"name":"setVrfKeyHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_vrfSubscriptionId","type":"uint64"}],"name":"setVrfSubscriptionId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vrfCallbackGasLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfCoordinator","outputs":[{"internalType":"contract VRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfKeyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfRequestConfirmations","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vrfRequests","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"bool","name":"fulfilled","type":"bool"},{"internalType":"bool","name":"minted","type":"bool"},{"internalType":"uint256","name":"randomWord","type":"uint256"},{"internalType":"uint256","name":"edition","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfSubscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a06040523480156200001157600080fd5b50604051620033e2380380620033e28339810160408190526200003491620001b7565b6001600160a01b0385166080526001805460ff1916905562000058600033620000fd565b600680546001600160a01b039889166001600160a01b0319918216179091556007805497891697821697909717909655600880549590971694909516939093179094556004556005805461ffff9093166c010000000000000000000000000261ffff60601b1963ffffffff90931668010000000000000000026001600160601b03199094166001600160401b039095169490941792909217169190911790556200026f565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200019a576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001593390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6001600160a01b0381168114620001b457600080fd5b50565b600080600080600080600060e0888a031215620001d357600080fd5b8751620001e0816200019e565b6020890151909750620001f3816200019e565b604089015190965062000206816200019e565b606089015160808a015191965094506001600160401b03811681146200022b57600080fd5b60a089015190935063ffffffff811681146200024657600080fd5b60c089015190925061ffff811681146200025f57600080fd5b8091505092959891949750929550565b6080516131506200029260003960008181610d7f0152610dda01526131506000f3fe6080604052600436106102385760003560e01c80638456cb5911610138578063a3e56fa8116100b0578063d547741f1161007f578063e135651e11610064578063e135651e146107b2578063ed647d21146107df578063f08103091461081957600080fd5b8063d547741f1461075e578063d853015e1461077e57600080fd5b8063a3e56fa8146106eb578063a4eb718c1461070b578063b80d07d91461072b578063c36df2d61461073e57600080fd5b80638c424f091161010757806391d14854116100ec57806391d1485414610665578063a217fddf146106a9578063a3213981146106be57600080fd5b80638c424f09146106255780638e03f5d61461064557600080fd5b80638456cb591461058457806385f438c11461059957806386b714e2146105cd5780638824f5a71461060557600080fd5b806336568abe116101cb5780633f791a721161019a5780635756716d1161017f5780635756716d1461050e578063598bc4861461052e5780635c975abb1461056c57600080fd5b80633f791a72146104cc57806349c4416e146104e157600080fd5b806336568abe1461042c5780633b7ed7341461044c5780633ebcf99d1461048a5780633f4ba83a146104b757600080fd5b80631fe543e3116102075780631fe543e31461039c578063248a9ca3146103bc5780632e1a7d4d146103ec5780632f2ff15d1461040c57600080fd5b806301ffc9a714610244578063041d443e146102795780631a1d92521461029d5780631e32cd4f1461037a57600080fd5b3661023f57005b600080fd5b34801561025057600080fd5b5061026461025f366004612902565b610839565b60405190151581526020015b60405180910390f35b34801561028557600080fd5b5061028f60045481565b604051908152602001610270565b3480156102a957600080fd5b5061033b6102b8366004612944565b60026020819052600091825260409091208054600182015491909201546001600160a01b0383169260ff740100000000000000000000000000000000000000008204811693750100000000000000000000000000000000000000000083048216937601000000000000000000000000000000000000000000009093049091169186565b604080516001600160a01b03909716875294151560208701529215159385019390935215156060840152608083019190915260a082015260c001610270565b34801561038657600080fd5b5061039a6103953660046129f2565b6108d2565b005b3480156103a857600080fd5b5061039a6103b73660046129f2565b610d74565b3480156103c857600080fd5b5061028f6103d7366004612944565b60009081526020819052604090206001015490565b3480156103f857600080fd5b5061039a610407366004612944565b610e15565b34801561041857600080fd5b5061039a610427366004612ab0565b610edc565b34801561043857600080fd5b5061039a610447366004612ab0565b610f01565b34801561045857600080fd5b506005546104759068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610270565b34801561049657600080fd5b506104aa6104a5366004612944565b610f89565b6040516102709190612b00565b3480156104c357600080fd5b5061039a611014565b3480156104d857600080fd5b5061039a611049565b3480156104ed57600080fd5b506105016104fc366004612b41565b6111da565b6040516102709190612bc9565b34801561051a57600080fd5b5061028f610529366004612ab0565b61128c565b34801561053a57600080fd5b50600554610559906c01000000000000000000000000900461ffff1681565b60405161ffff9091168152602001610270565b34801561057857600080fd5b5060015460ff16610264565b34801561059057600080fd5b5061039a611322565b3480156105a557600080fd5b5061028f7f10dac8c06a04bec0b551627dad28bc00d6516b0caacd1c7b345fcdb5211334e481565b3480156105d957600080fd5b506007546105ed906001600160a01b031681565b6040516001600160a01b039091168152602001610270565b34801561061157600080fd5b5061039a610620366004612bdc565b611354565b34801561063157600080fd5b5061039a610640366004612c00565b6113c4565b34801561065157600080fd5b506006546105ed906001600160a01b031681565b34801561067157600080fd5b50610264610680366004612ab0565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156106b557600080fd5b5061028f600081565b3480156106ca57600080fd5b506106de6106d9366004612944565b611429565b6040516102709190612c1b565b3480156106f757600080fd5b506008546105ed906001600160a01b031681565b34801561071757600080fd5b5061039a610726366004612ce2565b6114fd565b61028f6107393660046129f2565b61156b565b34801561074a57600080fd5b5061039a610759366004612944565b611afe565b34801561076a57600080fd5b5061039a610779366004612ab0565b611b2e565b34801561078a57600080fd5b5061028f7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf081565b3480156107be57600080fd5b5061028f6107cd366004612c00565b60036020526000908152604090205481565b3480156107eb57600080fd5b506005546108009067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610270565b34801561082557600080fd5b5061039a610834366004612d08565b611b53565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806108cc57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6108da611bb9565b6007546040517fa3213981000000000000000000000000000000000000000000000000000000008152600481018490526000916001600160a01b03169063a32139819060240161014060405180830381865afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612d6d565b6007546040517f5756716d000000000000000000000000000000000000000000000000000000008152600481018690523360248201529192506000916001600160a01b0390911690635756716d90604401602060405180830381865afa1580156109d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f49190612e1b565b90508160c0015115610a4d5760405162461bcd60e51b815260206004820152600b60248201527f5061636b2070617573656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600082602001516cffffffffffffffffffffffffff1611610ab05760405162461bcd60e51b815260206004820152601260248201527f4e6f2066726565207061636b73206c65667400000000000000000000000000006044820152606401610a44565b816060015162ffffff168110610b085760405162461bcd60e51b815260206004820152601560248201527f4d61782066726565207061636b73206d696e74656400000000000000000000006044820152606401610a44565b8160a0015115610bb257604080513360208201526000910160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610b64848460e0015183611c0e565b610bb05760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610a44565b505b60075460208301516001600160a01b039091169063e3d898be908690610bda90600190612e4a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526cffffffffffffffffffffffffff166024820152604401600060405180830381600087803b158015610c3f57600080fd5b505af1158015610c53573d6000803e3d6000fd5b50506007546001600160a01b0316915063b72dfed690508533610c77856001612e70565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b0390911660248301526044820152606401600060405180830381600087803b158015610cdd57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000033606090811b8216602084015241901b1660348201524460488201524560688201524260888201526000925060a80190506040516020818303038152906040528051906020012060001c9050610d6d8582611c24565b5050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e07576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610a44565b610e118282611f4d565b5050565b7f10dac8c06a04bec0b551627dad28bc00d6516b0caacd1c7b345fcdb5211334e4610e3f816120a7565b604051600090339084908381818185875af1925050503d8060008114610e81576040519150601f19603f3d011682016040523d82523d6000602084013e610e86565b606091505b5050905080610ed75760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610a44565b505050565b600082815260208190526040902060010154610ef7816120a7565b610ed783836120b1565b6001600160a01b0381163314610f7f5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610a44565b610e11828261214f565b6007546040517f3ebcf99d000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690633ebcf99d90602401600060405180830381865afa158015610fec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108cc9190810190612e83565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061103e816120a7565b6110466121ce565b50565b611051611bb9565b3360009081526003602052604081205490036110af5760405162461bcd60e51b815260206004820152601260248201527f4e6f2070656e64696e67207265717565737400000000000000000000000000006044820152606401610a44565b33600090815260036020908152604080832054808452600280845293829020825160c08101845281546001600160a01b038116825260ff74010000000000000000000000000000000000000000820481161515968301969096527501000000000000000000000000000000000000000000810486161515948201859052760100000000000000000000000000000000000000000000900490941615156060850152600181015460808501529093015460a08301526111af5760405162461bcd60e51b815260206004820152601560248201527f52657175657374206e6f742066756c66696c6c656400000000000000000000006044820152606401610a44565b600160608201523360009081526003602052604081205560a08101516080820151610e119190611c24565b6007546040517f49c4416e0000000000000000000000000000000000000000000000000000000081526004810187905260248101869052604481018590526064810184905282151560848201526060916001600160a01b0316906349c4416e9060a401600060405180830381865afa15801561125a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112829190810190612f17565b9695505050505050565b6007546040517f5756716d000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0383811660248301526000921690635756716d90604401602060405180830381865afa1580156112f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131b9190612e1b565b9392505050565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061134c816120a7565b611046612220565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061137e816120a7565b506005805461ffff9092166c01000000000000000000000000027fffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffffffff909216919091179055565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf06113ee816120a7565b50600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6040805161014081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082015260075491517fa32139810000000000000000000000000000000000000000000000000000000081526004810184905290916001600160a01b03169063a32139819060240161014060405180830381865afa1580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190612d6d565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611527816120a7565b506005805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055565b6000611575611bb9565b6007546040517fa3213981000000000000000000000000000000000000000000000000000000008152600481018590526000916001600160a01b03169063a32139819060240161014060405180830381865afa1580156115d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fd9190612d6d565b90508060c00151156116515760405162461bcd60e51b815260206004820152600b60248201527f5061636b207061757365640000000000000000000000000000000000000000006044820152606401610a44565b600081604001516cffffffffffffffffffffffffff16116116b45760405162461bcd60e51b815260206004820152600d60248201527f4e6f207061636b73206c656674000000000000000000000000000000000000006044820152606401610a44565b805134146117045760405162461bcd60e51b815260206004820152601060248201527f496e636f727265637420616d6f756e74000000000000000000000000000000006044820152606401610a44565b33600090815260036020526040902054156117615760405162461bcd60e51b815260206004820152601760248201527f5265717565737420616c72656164792070656e64696e670000000000000000006044820152606401610a44565b8060a001511561180b57604080513360208201526000910160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012090506117bd848360e0015183611c0e565b6118095760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610a44565b505b60075460408201516001600160a01b03909116906345b507c990869061183390600190612e4a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526cffffffffffffffffffffffffff166024820152604401600060405180830381600087803b15801561189857600080fd5b505af11580156118ac573d6000803e3d6000fd5b5050600854600480546005546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081529283019190915267ffffffffffffffff811660248301526c01000000000000000000000000810461ffff16604483015268010000000000000000900463ffffffff166064820152600160848201526001600160a01b039091169250635d3b1d30915060a4016020604051808303816000875af1158015611962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119869190612e1b565b6040805160c08101825233808252600160208084018281526000858701818152606087018281526080880183815260a089018f81528b855260028088528b86209a518b549751955194511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff951515750100000000000000000000000000000000000000000002959095167fffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff96151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009099166001600160a01b0392909216919091179790971794909416959095179190911788555194870194909455905194909201939093558181526003909252828220849055915192945084927f0c27e43af6588b65dccc4465720ef720b7cf45f5fba352df8607ae1cfea9089b9190a35092915050565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611b28816120a7565b50600455565b600082815260208190526040902060010154611b49816120a7565b610ed7838361214f565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611b7d816120a7565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b60015460ff1615611c0c5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a44565b565b600082611c1b858461225b565b14949350505050565b60408051600380825260808201909252600091602082016060803683370190505090506000611c5483600c6122a8565b9050611ccd84600083600081518110611c6f57611c6f612fa8565b602002602001015184600181518110611c8a57611c8a612fa8565b602002602001015185600281518110611ca557611ca5612fa8565b602002602001015186600381518110611cc057611cc0612fa8565b602002602001015161235d565b82600081518110611ce057611ce0612fa8565b602002602001018181525050611d5684600183600481518110611d0557611d05612fa8565b602002602001015184600581518110611d2057611d20612fa8565b602002602001015185600681518110611d3b57611d3b612fa8565b602002602001015186600781518110611cc057611cc0612fa8565b82600181518110611d6957611d69612fa8565b602002602001018181525050611ddf84600283600881518110611d8e57611d8e612fa8565b602002602001015184600981518110611da957611da9612fa8565b602002602001015185600a81518110611dc457611dc4612fa8565b602002602001015186600b81518110611cc057611cc0612fa8565b82600281518110611df257611df2612fa8565b602090810291909101015260408051600380825260808201909252600091816020016020820280368337019050509050600181600081518110611e3757611e37612fa8565b602002602001018181525050600181600181518110611e5857611e58612fa8565b602002602001018181525050600181600281518110611e7957611e79612fa8565b60209081029190910101526006546040517f1f7fdffa0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690631f7fdffa90611ed190339087908690600401612fbe565b600060405180830381600087803b158015611eeb57600080fd5b505af1158015611eff573d6000803e3d6000fd5b50505050336001600160a01b03167fae0b83e873f7a07263aeae5493db6f6b1bb1e5737e6c5c78d8bd4cc2376678c08685604051611f3e92919061300e565b60405180910390a25050505050565b60008281526002602052604090205474010000000000000000000000000000000000000000900460ff16611fc35760405162461bcd60e51b815260206004820152601160248201527f72657175657374206e6f7420666f756e640000000000000000000000000000006044820152606401610a44565b600082815260026020526040812080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055815182919061202057612020612fa8565b6020908102919091018101516000848152600290925260408220600181019190915554825184926001600160a01b03909216917f1165aa98d42fbaef9bacc273d7b5cca8edc94909519f8f949ec33562963c87e49185919061208457612084612fa8565b602002602001015160405161209b91815260200190565b60405180910390a35050565b6110468133612517565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610e11576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561210b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610e11576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6121d661258a565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b612228611bb9565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612203565b600081815b84518110156122a05761228c8286838151811061227f5761227f612fa8565b60200260200101516125dc565b9150806122988161302f565b915050612260565b509392505050565b60608167ffffffffffffffff8111156122c3576122c361295d565b6040519080825280602002602001820160405280156122ec578160200160208202803683370190505b50905060005b828110156123565760408051602081018690529081018290526060016040516020818303038152906040528051906020012060001c82828151811061233957612339612fa8565b60209081029190910101528061234e8161302f565b9150506122f2565b5092915050565b6000806123698661260b565b905060006123768661265e565b90506000612383866126b1565b6007546040517f49c4416e000000000000000000000000000000000000000000000000000000008152600481018d9052602481018c9052604481018690526064810185905282151560848201529192506001600160a01b0316906349c4416e9060a401600060405180830381865afa158015612403573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261242b9190810190612f17565b51600003612437575060005b6007546040517f49c4416e000000000000000000000000000000000000000000000000000000008152600481018c9052602481018b9052604481018590526064810184905282151560848201526000916001600160a01b0316906349c4416e9060a401600060405180830381865afa1580156124b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124df9190810190612f17565b9050808151876124ef9190613049565b815181106124ff576124ff612fa8565b60200260200101519450505050509695505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610e1157612548816126c7565b6125538360206126d9565b60405160200161256492919061306b565b60408051601f198184030181529082905262461bcd60e51b8252610a4491600401612b00565b60015460ff16611c0c5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a44565b60008183106125f857600082815260208490526040902061131b565b600083815260208390526040902061131b565b60008061261a61271084613049565b9050611ce381101561262f5750600192915050565b6126d98110156126425750600292915050565b61270b8110156126555750600392915050565b50600492915050565b60008061266d61271084613049565b90506112c08110156126825750600092915050565b611c848110156126955750600192915050565b6124b88110156126a85750600292915050565b50600392915050565b60006126be606483613049565b60011492915050565b60606108cc6001600160a01b03831660145b606060006126e88360026130ec565b6126f3906002612e70565b67ffffffffffffffff81111561270b5761270b61295d565b6040519080825280601f01601f191660200182016040528015612735576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061276c5761276c612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106127cf576127cf612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061280b8460026130ec565b612816906001612e70565b90505b60018111156128b3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061285757612857612fa8565b1a60f81b82828151811061286d5761286d612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936128ac81613103565b9050612819565b50831561131b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a44565b60006020828403121561291457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461131b57600080fd5b60006020828403121561295657600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156129975761299761295d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156129c6576129c661295d565b604052919050565b600067ffffffffffffffff8211156129e8576129e861295d565b5060051b60200190565b60008060408385031215612a0557600080fd5b8235915060208084013567ffffffffffffffff811115612a2457600080fd5b8401601f81018613612a3557600080fd5b8035612a48612a43826129ce565b61299d565b81815260059190911b82018301908381019088831115612a6757600080fd5b928401925b82841015612a8557833582529284019290840190612a6c565b80955050505050509250929050565b80356001600160a01b0381168114612aab57600080fd5b919050565b60008060408385031215612ac357600080fd5b82359150612ad360208401612a94565b90509250929050565b60005b83811015612af7578181015183820152602001612adf565b50506000910152565b6020815260008251806020840152612b1f816040850160208701612adc565b601f01601f19169190910160400192915050565b801515811461104657600080fd5b600080600080600060a08688031215612b5957600080fd5b853594506020860135935060408601359250606086013591506080860135612b8081612b33565b809150509295509295909350565b600081518084526020808501945080840160005b83811015612bbe57815187529582019590820190600101612ba2565b509495945050505050565b60208152600061131b6020830184612b8e565b600060208284031215612bee57600080fd5b813561ffff8116811461131b57600080fd5b600060208284031215612c1257600080fd5b61131b82612a94565b81518152602080830151610140830191612c45908401826cffffffffffffffffffffffffff169052565b506040830151612c6660408401826cffffffffffffffffffffffffff169052565b506060830151612c7d606084018262ffffff169052565b506080830151612c91608084018215159052565b5060a0830151612ca560a084018215159052565b5060c0830151612cb960c084018215159052565b5060e083015160e083015261010080840151818401525061012080840151818401525092915050565b600060208284031215612cf457600080fd5b813563ffffffff8116811461131b57600080fd5b600060208284031215612d1a57600080fd5b813567ffffffffffffffff8116811461131b57600080fd5b80516cffffffffffffffffffffffffff81168114612aab57600080fd5b805162ffffff81168114612aab57600080fd5b8051612aab81612b33565b60006101408284031215612d8057600080fd5b612d88612973565b82518152612d9860208401612d32565b6020820152612da960408401612d32565b6040820152612dba60608401612d4f565b6060820152612dcb60808401612d62565b6080820152612ddc60a08401612d62565b60a0820152612ded60c08401612d62565b60c082015260e083810151908201526101008084015190820152610120928301519281019290925250919050565b600060208284031215612e2d57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6cffffffffffffffffffffffffff82811682821603908082111561235657612356612e34565b808201808211156108cc576108cc612e34565b600060208284031215612e9557600080fd5b815167ffffffffffffffff80821115612ead57600080fd5b818401915084601f830112612ec157600080fd5b815181811115612ed357612ed361295d565b612ee66020601f19601f8401160161299d565b9150808252856020828501011115612efd57600080fd5b612f0e816020840160208601612adc565b50949350505050565b60006020808385031215612f2a57600080fd5b825167ffffffffffffffff811115612f4157600080fd5b8301601f81018513612f5257600080fd5b8051612f60612a43826129ce565b81815260059190911b82018301908381019087831115612f7f57600080fd5b928401925b82841015612f9d57835182529284019290840190612f84565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0384168152608060208201526000612fe06080830185612b8e565b8281036040840152612ff28185612b8e565b8381036060909401939093525050600081526020019392505050565b8281526040602082015260006130276040830184612b8e565b949350505050565b6000600019820361304257613042612e34565b5060010190565b60008261306657634e487b7160e01b600052601260045260246000fd5b500690565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516130a3816017850160208801612adc565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516130e0816028840160208801612adc565b01602801949350505050565b80820281158282048414176108cc576108cc612e34565b60008161311257613112612e34565b50600019019056fea26469706673582212201fc46e54f9a1935b7604e78ab41dcee02df6b32192eef63521dd11a8e360b53264736f6c634300081100330000000000000000000000004668ec63111640be2bcbaa23af1b86192bbea5f90000000000000000000000008a96d9832e22c6e05a8d7fc845ee1902cb419065000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000003
Deployed Bytecode
0x6080604052600436106102385760003560e01c80638456cb5911610138578063a3e56fa8116100b0578063d547741f1161007f578063e135651e11610064578063e135651e146107b2578063ed647d21146107df578063f08103091461081957600080fd5b8063d547741f1461075e578063d853015e1461077e57600080fd5b8063a3e56fa8146106eb578063a4eb718c1461070b578063b80d07d91461072b578063c36df2d61461073e57600080fd5b80638c424f091161010757806391d14854116100ec57806391d1485414610665578063a217fddf146106a9578063a3213981146106be57600080fd5b80638c424f09146106255780638e03f5d61461064557600080fd5b80638456cb591461058457806385f438c11461059957806386b714e2146105cd5780638824f5a71461060557600080fd5b806336568abe116101cb5780633f791a721161019a5780635756716d1161017f5780635756716d1461050e578063598bc4861461052e5780635c975abb1461056c57600080fd5b80633f791a72146104cc57806349c4416e146104e157600080fd5b806336568abe1461042c5780633b7ed7341461044c5780633ebcf99d1461048a5780633f4ba83a146104b757600080fd5b80631fe543e3116102075780631fe543e31461039c578063248a9ca3146103bc5780632e1a7d4d146103ec5780632f2ff15d1461040c57600080fd5b806301ffc9a714610244578063041d443e146102795780631a1d92521461029d5780631e32cd4f1461037a57600080fd5b3661023f57005b600080fd5b34801561025057600080fd5b5061026461025f366004612902565b610839565b60405190151581526020015b60405180910390f35b34801561028557600080fd5b5061028f60045481565b604051908152602001610270565b3480156102a957600080fd5b5061033b6102b8366004612944565b60026020819052600091825260409091208054600182015491909201546001600160a01b0383169260ff740100000000000000000000000000000000000000008204811693750100000000000000000000000000000000000000000083048216937601000000000000000000000000000000000000000000009093049091169186565b604080516001600160a01b03909716875294151560208701529215159385019390935215156060840152608083019190915260a082015260c001610270565b34801561038657600080fd5b5061039a6103953660046129f2565b6108d2565b005b3480156103a857600080fd5b5061039a6103b73660046129f2565b610d74565b3480156103c857600080fd5b5061028f6103d7366004612944565b60009081526020819052604090206001015490565b3480156103f857600080fd5b5061039a610407366004612944565b610e15565b34801561041857600080fd5b5061039a610427366004612ab0565b610edc565b34801561043857600080fd5b5061039a610447366004612ab0565b610f01565b34801561045857600080fd5b506005546104759068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610270565b34801561049657600080fd5b506104aa6104a5366004612944565b610f89565b6040516102709190612b00565b3480156104c357600080fd5b5061039a611014565b3480156104d857600080fd5b5061039a611049565b3480156104ed57600080fd5b506105016104fc366004612b41565b6111da565b6040516102709190612bc9565b34801561051a57600080fd5b5061028f610529366004612ab0565b61128c565b34801561053a57600080fd5b50600554610559906c01000000000000000000000000900461ffff1681565b60405161ffff9091168152602001610270565b34801561057857600080fd5b5060015460ff16610264565b34801561059057600080fd5b5061039a611322565b3480156105a557600080fd5b5061028f7f10dac8c06a04bec0b551627dad28bc00d6516b0caacd1c7b345fcdb5211334e481565b3480156105d957600080fd5b506007546105ed906001600160a01b031681565b6040516001600160a01b039091168152602001610270565b34801561061157600080fd5b5061039a610620366004612bdc565b611354565b34801561063157600080fd5b5061039a610640366004612c00565b6113c4565b34801561065157600080fd5b506006546105ed906001600160a01b031681565b34801561067157600080fd5b50610264610680366004612ab0565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156106b557600080fd5b5061028f600081565b3480156106ca57600080fd5b506106de6106d9366004612944565b611429565b6040516102709190612c1b565b3480156106f757600080fd5b506008546105ed906001600160a01b031681565b34801561071757600080fd5b5061039a610726366004612ce2565b6114fd565b61028f6107393660046129f2565b61156b565b34801561074a57600080fd5b5061039a610759366004612944565b611afe565b34801561076a57600080fd5b5061039a610779366004612ab0565b611b2e565b34801561078a57600080fd5b5061028f7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf081565b3480156107be57600080fd5b5061028f6107cd366004612c00565b60036020526000908152604090205481565b3480156107eb57600080fd5b506005546108009067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610270565b34801561082557600080fd5b5061039a610834366004612d08565b611b53565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806108cc57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6108da611bb9565b6007546040517fa3213981000000000000000000000000000000000000000000000000000000008152600481018490526000916001600160a01b03169063a32139819060240161014060405180830381865afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612d6d565b6007546040517f5756716d000000000000000000000000000000000000000000000000000000008152600481018690523360248201529192506000916001600160a01b0390911690635756716d90604401602060405180830381865afa1580156109d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f49190612e1b565b90508160c0015115610a4d5760405162461bcd60e51b815260206004820152600b60248201527f5061636b2070617573656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600082602001516cffffffffffffffffffffffffff1611610ab05760405162461bcd60e51b815260206004820152601260248201527f4e6f2066726565207061636b73206c65667400000000000000000000000000006044820152606401610a44565b816060015162ffffff168110610b085760405162461bcd60e51b815260206004820152601560248201527f4d61782066726565207061636b73206d696e74656400000000000000000000006044820152606401610a44565b8160a0015115610bb257604080513360208201526000910160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610b64848460e0015183611c0e565b610bb05760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610a44565b505b60075460208301516001600160a01b039091169063e3d898be908690610bda90600190612e4a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526cffffffffffffffffffffffffff166024820152604401600060405180830381600087803b158015610c3f57600080fd5b505af1158015610c53573d6000803e3d6000fd5b50506007546001600160a01b0316915063b72dfed690508533610c77856001612e70565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b0390911660248301526044820152606401600060405180830381600087803b158015610cdd57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000033606090811b8216602084015241901b1660348201524460488201524560688201524260888201526000925060a80190506040516020818303038152906040528051906020012060001c9050610d6d8582611c24565b5050505050565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091614610e07576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610a44565b610e118282611f4d565b5050565b7f10dac8c06a04bec0b551627dad28bc00d6516b0caacd1c7b345fcdb5211334e4610e3f816120a7565b604051600090339084908381818185875af1925050503d8060008114610e81576040519150601f19603f3d011682016040523d82523d6000602084013e610e86565b606091505b5050905080610ed75760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610a44565b505050565b600082815260208190526040902060010154610ef7816120a7565b610ed783836120b1565b6001600160a01b0381163314610f7f5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610a44565b610e11828261214f565b6007546040517f3ebcf99d000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690633ebcf99d90602401600060405180830381865afa158015610fec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108cc9190810190612e83565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061103e816120a7565b6110466121ce565b50565b611051611bb9565b3360009081526003602052604081205490036110af5760405162461bcd60e51b815260206004820152601260248201527f4e6f2070656e64696e67207265717565737400000000000000000000000000006044820152606401610a44565b33600090815260036020908152604080832054808452600280845293829020825160c08101845281546001600160a01b038116825260ff74010000000000000000000000000000000000000000820481161515968301969096527501000000000000000000000000000000000000000000810486161515948201859052760100000000000000000000000000000000000000000000900490941615156060850152600181015460808501529093015460a08301526111af5760405162461bcd60e51b815260206004820152601560248201527f52657175657374206e6f742066756c66696c6c656400000000000000000000006044820152606401610a44565b600160608201523360009081526003602052604081205560a08101516080820151610e119190611c24565b6007546040517f49c4416e0000000000000000000000000000000000000000000000000000000081526004810187905260248101869052604481018590526064810184905282151560848201526060916001600160a01b0316906349c4416e9060a401600060405180830381865afa15801561125a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112829190810190612f17565b9695505050505050565b6007546040517f5756716d000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0383811660248301526000921690635756716d90604401602060405180830381865afa1580156112f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131b9190612e1b565b9392505050565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061134c816120a7565b611046612220565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf061137e816120a7565b506005805461ffff9092166c01000000000000000000000000027fffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffffffff909216919091179055565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf06113ee816120a7565b50600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6040805161014081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082015260075491517fa32139810000000000000000000000000000000000000000000000000000000081526004810184905290916001600160a01b03169063a32139819060240161014060405180830381865afa1580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190612d6d565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611527816120a7565b506005805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055565b6000611575611bb9565b6007546040517fa3213981000000000000000000000000000000000000000000000000000000008152600481018590526000916001600160a01b03169063a32139819060240161014060405180830381865afa1580156115d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fd9190612d6d565b90508060c00151156116515760405162461bcd60e51b815260206004820152600b60248201527f5061636b207061757365640000000000000000000000000000000000000000006044820152606401610a44565b600081604001516cffffffffffffffffffffffffff16116116b45760405162461bcd60e51b815260206004820152600d60248201527f4e6f207061636b73206c656674000000000000000000000000000000000000006044820152606401610a44565b805134146117045760405162461bcd60e51b815260206004820152601060248201527f496e636f727265637420616d6f756e74000000000000000000000000000000006044820152606401610a44565b33600090815260036020526040902054156117615760405162461bcd60e51b815260206004820152601760248201527f5265717565737420616c72656164792070656e64696e670000000000000000006044820152606401610a44565b8060a001511561180b57604080513360208201526000910160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012090506117bd848360e0015183611c0e565b6118095760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610a44565b505b60075460408201516001600160a01b03909116906345b507c990869061183390600190612e4a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526cffffffffffffffffffffffffff166024820152604401600060405180830381600087803b15801561189857600080fd5b505af11580156118ac573d6000803e3d6000fd5b5050600854600480546005546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081529283019190915267ffffffffffffffff811660248301526c01000000000000000000000000810461ffff16604483015268010000000000000000900463ffffffff166064820152600160848201526001600160a01b039091169250635d3b1d30915060a4016020604051808303816000875af1158015611962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119869190612e1b565b6040805160c08101825233808252600160208084018281526000858701818152606087018281526080880183815260a089018f81528b855260028088528b86209a518b549751955194511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff951515750100000000000000000000000000000000000000000002959095167fffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff96151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009099166001600160a01b0392909216919091179790971794909416959095179190911788555194870194909455905194909201939093558181526003909252828220849055915192945084927f0c27e43af6588b65dccc4465720ef720b7cf45f5fba352df8607ae1cfea9089b9190a35092915050565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611b28816120a7565b50600455565b600082815260208190526040902060010154611b49816120a7565b610ed7838361214f565b7f3b49a237fe2d18fa4d9642b8a0e065923cceb71b797783b619a030a61d848bf0611b7d816120a7565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b60015460ff1615611c0c5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610a44565b565b600082611c1b858461225b565b14949350505050565b60408051600380825260808201909252600091602082016060803683370190505090506000611c5483600c6122a8565b9050611ccd84600083600081518110611c6f57611c6f612fa8565b602002602001015184600181518110611c8a57611c8a612fa8565b602002602001015185600281518110611ca557611ca5612fa8565b602002602001015186600381518110611cc057611cc0612fa8565b602002602001015161235d565b82600081518110611ce057611ce0612fa8565b602002602001018181525050611d5684600183600481518110611d0557611d05612fa8565b602002602001015184600581518110611d2057611d20612fa8565b602002602001015185600681518110611d3b57611d3b612fa8565b602002602001015186600781518110611cc057611cc0612fa8565b82600181518110611d6957611d69612fa8565b602002602001018181525050611ddf84600283600881518110611d8e57611d8e612fa8565b602002602001015184600981518110611da957611da9612fa8565b602002602001015185600a81518110611dc457611dc4612fa8565b602002602001015186600b81518110611cc057611cc0612fa8565b82600281518110611df257611df2612fa8565b602090810291909101015260408051600380825260808201909252600091816020016020820280368337019050509050600181600081518110611e3757611e37612fa8565b602002602001018181525050600181600181518110611e5857611e58612fa8565b602002602001018181525050600181600281518110611e7957611e79612fa8565b60209081029190910101526006546040517f1f7fdffa0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690631f7fdffa90611ed190339087908690600401612fbe565b600060405180830381600087803b158015611eeb57600080fd5b505af1158015611eff573d6000803e3d6000fd5b50505050336001600160a01b03167fae0b83e873f7a07263aeae5493db6f6b1bb1e5737e6c5c78d8bd4cc2376678c08685604051611f3e92919061300e565b60405180910390a25050505050565b60008281526002602052604090205474010000000000000000000000000000000000000000900460ff16611fc35760405162461bcd60e51b815260206004820152601160248201527f72657175657374206e6f7420666f756e640000000000000000000000000000006044820152606401610a44565b600082815260026020526040812080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055815182919061202057612020612fa8565b6020908102919091018101516000848152600290925260408220600181019190915554825184926001600160a01b03909216917f1165aa98d42fbaef9bacc273d7b5cca8edc94909519f8f949ec33562963c87e49185919061208457612084612fa8565b602002602001015160405161209b91815260200190565b60405180910390a35050565b6110468133612517565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610e11576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561210b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610e11576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6121d661258a565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b612228611bb9565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612203565b600081815b84518110156122a05761228c8286838151811061227f5761227f612fa8565b60200260200101516125dc565b9150806122988161302f565b915050612260565b509392505050565b60608167ffffffffffffffff8111156122c3576122c361295d565b6040519080825280602002602001820160405280156122ec578160200160208202803683370190505b50905060005b828110156123565760408051602081018690529081018290526060016040516020818303038152906040528051906020012060001c82828151811061233957612339612fa8565b60209081029190910101528061234e8161302f565b9150506122f2565b5092915050565b6000806123698661260b565b905060006123768661265e565b90506000612383866126b1565b6007546040517f49c4416e000000000000000000000000000000000000000000000000000000008152600481018d9052602481018c9052604481018690526064810185905282151560848201529192506001600160a01b0316906349c4416e9060a401600060405180830381865afa158015612403573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261242b9190810190612f17565b51600003612437575060005b6007546040517f49c4416e000000000000000000000000000000000000000000000000000000008152600481018c9052602481018b9052604481018590526064810184905282151560848201526000916001600160a01b0316906349c4416e9060a401600060405180830381865afa1580156124b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124df9190810190612f17565b9050808151876124ef9190613049565b815181106124ff576124ff612fa8565b60200260200101519450505050509695505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610e1157612548816126c7565b6125538360206126d9565b60405160200161256492919061306b565b60408051601f198184030181529082905262461bcd60e51b8252610a4491600401612b00565b60015460ff16611c0c5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a44565b60008183106125f857600082815260208490526040902061131b565b600083815260208390526040902061131b565b60008061261a61271084613049565b9050611ce381101561262f5750600192915050565b6126d98110156126425750600292915050565b61270b8110156126555750600392915050565b50600492915050565b60008061266d61271084613049565b90506112c08110156126825750600092915050565b611c848110156126955750600192915050565b6124b88110156126a85750600292915050565b50600392915050565b60006126be606483613049565b60011492915050565b60606108cc6001600160a01b03831660145b606060006126e88360026130ec565b6126f3906002612e70565b67ffffffffffffffff81111561270b5761270b61295d565b6040519080825280601f01601f191660200182016040528015612735576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061276c5761276c612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106127cf576127cf612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061280b8460026130ec565b612816906001612e70565b90505b60018111156128b3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061285757612857612fa8565b1a60f81b82828151811061286d5761286d612fa8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936128ac81613103565b9050612819565b50831561131b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a44565b60006020828403121561291457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461131b57600080fd5b60006020828403121561295657600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff811182821017156129975761299761295d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156129c6576129c661295d565b604052919050565b600067ffffffffffffffff8211156129e8576129e861295d565b5060051b60200190565b60008060408385031215612a0557600080fd5b8235915060208084013567ffffffffffffffff811115612a2457600080fd5b8401601f81018613612a3557600080fd5b8035612a48612a43826129ce565b61299d565b81815260059190911b82018301908381019088831115612a6757600080fd5b928401925b82841015612a8557833582529284019290840190612a6c565b80955050505050509250929050565b80356001600160a01b0381168114612aab57600080fd5b919050565b60008060408385031215612ac357600080fd5b82359150612ad360208401612a94565b90509250929050565b60005b83811015612af7578181015183820152602001612adf565b50506000910152565b6020815260008251806020840152612b1f816040850160208701612adc565b601f01601f19169190910160400192915050565b801515811461104657600080fd5b600080600080600060a08688031215612b5957600080fd5b853594506020860135935060408601359250606086013591506080860135612b8081612b33565b809150509295509295909350565b600081518084526020808501945080840160005b83811015612bbe57815187529582019590820190600101612ba2565b509495945050505050565b60208152600061131b6020830184612b8e565b600060208284031215612bee57600080fd5b813561ffff8116811461131b57600080fd5b600060208284031215612c1257600080fd5b61131b82612a94565b81518152602080830151610140830191612c45908401826cffffffffffffffffffffffffff169052565b506040830151612c6660408401826cffffffffffffffffffffffffff169052565b506060830151612c7d606084018262ffffff169052565b506080830151612c91608084018215159052565b5060a0830151612ca560a084018215159052565b5060c0830151612cb960c084018215159052565b5060e083015160e083015261010080840151818401525061012080840151818401525092915050565b600060208284031215612cf457600080fd5b813563ffffffff8116811461131b57600080fd5b600060208284031215612d1a57600080fd5b813567ffffffffffffffff8116811461131b57600080fd5b80516cffffffffffffffffffffffffff81168114612aab57600080fd5b805162ffffff81168114612aab57600080fd5b8051612aab81612b33565b60006101408284031215612d8057600080fd5b612d88612973565b82518152612d9860208401612d32565b6020820152612da960408401612d32565b6040820152612dba60608401612d4f565b6060820152612dcb60808401612d62565b6080820152612ddc60a08401612d62565b60a0820152612ded60c08401612d62565b60c082015260e083810151908201526101008084015190820152610120928301519281019290925250919050565b600060208284031215612e2d57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6cffffffffffffffffffffffffff82811682821603908082111561235657612356612e34565b808201808211156108cc576108cc612e34565b600060208284031215612e9557600080fd5b815167ffffffffffffffff80821115612ead57600080fd5b818401915084601f830112612ec157600080fd5b815181811115612ed357612ed361295d565b612ee66020601f19601f8401160161299d565b9150808252856020828501011115612efd57600080fd5b612f0e816020840160208601612adc565b50949350505050565b60006020808385031215612f2a57600080fd5b825167ffffffffffffffff811115612f4157600080fd5b8301601f81018513612f5257600080fd5b8051612f60612a43826129ce565b81815260059190911b82018301908381019087831115612f7f57600080fd5b928401925b82841015612f9d57835182529284019290840190612f84565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0384168152608060208201526000612fe06080830185612b8e565b8281036040840152612ff28185612b8e565b8381036060909401939093525050600081526020019392505050565b8281526040602082015260006130276040830184612b8e565b949350505050565b6000600019820361304257613042612e34565b5060010190565b60008261306657634e487b7160e01b600052601260045260246000fd5b500690565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516130a3816017850160208801612adc565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516130e0816028840160208801612adc565b01602801949350505050565b80820281158282048414176108cc576108cc612e34565b60008161311257613112612e34565b50600019019056fea26469706673582212201fc46e54f9a1935b7604e78ab41dcee02df6b32192eef63521dd11a8e360b53264736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004668ec63111640be2bcbaa23af1b86192bbea5f90000000000000000000000008a96d9832e22c6e05a8d7fc845ee1902cb419065000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000003
-----Decoded View---------------
Arg [0] : _altariusCards (address): 0x4668EC63111640bE2bCbAA23Af1B86192Bbea5f9
Arg [1] : _altariusMinterStorage (address): 0x8a96d9832e22C6e05a8d7fc845Ee1902cb419065
Arg [2] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [3] : _vrfKeyHash (bytes32): 0xff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Arg [4] : _vrfSubscriptionId (uint64): 0
Arg [5] : _vrfCallbackGasLimit (uint32): 100000
Arg [6] : _vrfRequestConfirmations (uint16): 3
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000004668ec63111640be2bcbaa23af1b86192bbea5f9
Arg [1] : 0000000000000000000000008a96d9832e22c6e05a8d7fc845ee1902cb419065
Arg [2] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [3] : ff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000000000000000000000000000000000000000186a0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.