Source Code
Latest 25 from a total of 25,521 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Toggle Pause | 10503852 | 457 days ago | IN | 0 ETH | 0.00000012 | ||||
| Forge Units | 10503547 | 457 days ago | IN | 0 ETH | 0.00000227 | ||||
| Forge Units | 10503453 | 457 days ago | IN | 0 ETH | 0.00000262 | ||||
| Forge Units | 10503143 | 457 days ago | IN | 0 ETH | 0.00000267 | ||||
| Forge Artifact | 10503113 | 457 days ago | IN | 0 ETH | 0.00000129 | ||||
| Forge Units | 10502987 | 457 days ago | IN | 0 ETH | 0.00000242 | ||||
| Forge Units | 10502957 | 457 days ago | IN | 0 ETH | 0.00000234 | ||||
| Reforge | 10502781 | 457 days ago | IN | 0 ETH | 0.00000241 | ||||
| Forge Units | 10502728 | 457 days ago | IN | 0 ETH | 0.00000288 | ||||
| Reforge | 10502725 | 457 days ago | IN | 0 ETH | 0.00000245 | ||||
| Forge Units | 10502419 | 457 days ago | IN | 0 ETH | 0.00000278 | ||||
| Forge Units | 10501178 | 457 days ago | IN | 0 ETH | 0.00000282 | ||||
| Reforge | 10500211 | 457 days ago | IN | 0 ETH | 0.00000239 | ||||
| Reforge | 10500193 | 457 days ago | IN | 0 ETH | 0.0000024 | ||||
| Reforge | 10500111 | 457 days ago | IN | 0 ETH | 0.00000243 | ||||
| Reforge | 10499704 | 457 days ago | IN | 0 ETH | 0.00000232 | ||||
| Forge Units | 10499580 | 457 days ago | IN | 0 ETH | 0.00000273 | ||||
| Forge Units | 10499359 | 457 days ago | IN | 0 ETH | 0.00000247 | ||||
| Forge Units | 10499032 | 457 days ago | IN | 0 ETH | 0.00000318 | ||||
| Forge Units | 10498933 | 457 days ago | IN | 0 ETH | 0.00000291 | ||||
| Forge Units | 10498433 | 457 days ago | IN | 0 ETH | 0.00000336 | ||||
| Reforge | 10498205 | 457 days ago | IN | 0 ETH | 0.00000323 | ||||
| Forge Units | 10498180 | 457 days ago | IN | 0 ETH | 0.00000387 | ||||
| Forge Units | 10497738 | 457 days ago | IN | 0 ETH | 0.00000379 | ||||
| Forge Units | 10497244 | 457 days ago | IN | 0 ETH | 0.0000036 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CardForgeV2
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/**
*Submitted for verification at blastscan.io on 2024-07-02
*/
// SPDX-License-Identifier: MIT
pragma solidity =0.8.20 ^0.8.20 ^0.8.4;
// lib/ERC721A-Upgradeable/contracts/IERC721AUpgradeable.sol
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs
/**
* @dev Interface of ERC721A.
*/
interface IERC721AUpgradeable {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external payable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external payable;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}
// lib/openzeppelin-contracts/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
/**
* @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;
}
}
// lib/solady/src/auth/Ownable.sol
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}
// lib/solady/src/utils/ECDSA.sol
/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
/// This is for more safety by default.
/// Use the `tryRecover` variants if you need to get the zero address back
/// upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
/// See: https://eips.ethereum.org/EIPS/eip-2098
/// This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
/// EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library ECDSA {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The signature is invalid.
error InvalidSignature();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RECOVERY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
for {} 1 {} {
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
if eq(mload(signature), 64) {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(mload(signature), 65) {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
break
}
result := 0
break
}
result :=
mload(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
for {} 1 {} {
if eq(signature.length, 64) {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(signature.length, 65) {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
break
}
result := 0
break
}
result :=
mload(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
result :=
mload(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
result :=
mload(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x01, // Start of output.
0x20 // Size of output.
)
)
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TRY-RECOVER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// WARNING!
// These functions will NOT revert upon recovery failure.
// Instead, they will return the zero address upon recovery failure.
// It is critical that the returned address is NEVER compared against
// a zero address (e.g. an uninitialized address variable).
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecover(bytes32 hash, bytes memory signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
for {} 1 {} {
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
if eq(mload(signature), 64) {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(mload(signature), 65) {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
break
}
result := 0
break
}
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x40, // Start of output.
0x20 // Size of output.
)
)
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
result := 1
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
for {} 1 {} {
if eq(signature.length, 64) {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
break
}
if eq(signature.length, 65) {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
break
}
result := 0
break
}
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
result, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x40, // Start of output.
0x20 // Size of output.
)
)
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x40, // Start of output.
0x20 // Size of output.
)
)
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
pop(
staticcall(
gas(), // Amount of gas left for the transaction.
1, // Address of `ecrecover`.
0x00, // Start of input.
0x80, // Size of input.
0x40, // Start of output.
0x20 // Size of output.
)
)
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an Ethereum Signed Message, created from a `hash`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
/// JSON-RPC method as part of EIP-191.
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x20, hash) // Store into scratch space for keccak256.
mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
}
}
/// @dev Returns an Ethereum Signed Message, created from `s`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
/// JSON-RPC method as part of EIP-191.
/// Note: Supports lengths of `s` up to 999999 bytes.
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let sLength := mload(s)
let o := 0x20
mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
mstore(0x00, 0x00)
// Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
for { let temp := sLength } 1 {} {
o := sub(o, 1)
mstore8(o, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
// Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
mstore(s, sLength) // Restore the length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}
// src/access/AccessRoles.sol
/**
* @title AccessRoles
* @notice This library contains all the valid roles within the protocol. Roles have been defined to mimic
* {Solady.OwnableRoles} roles.
*/
library AccessRoles {
/// `OwnableRoles._ROLE_0`
uint256 public constant GAME_MASTER_ROLE = 1 << 0;
/// `OwnableRoles._ROLE_1`
uint256 public constant SEEDER_ROLE = 1 << 1;
/// `OwnableRoles._ROLE_2`
uint256 public constant MINTER_ROLE = 1 << 2;
/// `OwnableRoles._ROLE_3`
uint256 public constant RESOLVER_ROLE = 1 << 3;
}
// src/interfaces/IBlast.sol
/**
* @title IBlast
* @notice Interface for Blast.
*/
interface IBlast {
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(
address contractAddress,
address recipientOfGas,
uint256 minClaimRateBips
)
external
returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(
address contractAddress,
address recipientOfGas,
uint256 gasToClaim,
uint256 gasSecondsToConsume
)
external
returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(address contractAddress)
external
view
returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}
// src/interfaces/ISeeder.sol
/**
* @title ISeeder
* @notice Interface for Seeder.
*/
interface ISeeder {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided as input.
*/
error ZeroAddress();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Emitted when the game seed is updated.
* @param oldSeed Old game seed.
* @param newSeed New game seed.
*/
event GameSeedUpdated(uint256 oldSeed, uint256 newSeed);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to get the current game seed and update it. The value returned
* is the game seed prior to the update.
*/
function getAndUpdateGameSeed() external returns (uint256);
/**
* Function used to view the current game seed.
*/
function currentGameSeed() external view returns (uint256);
}
// src/types/Game.sol
/**
* @title Game
* @notice This library contains shared data types and structures that are used within the game.
*/
/**
* Namespace used to encapsulate shared game data types and structures.
*/
library Game {
/**
* Enum encapsulating the various tiers that can be associated with a card.
*/
enum CardTier {
UNDEFINED,
C,
B,
A,
S,
SS,
SSS
}
/**
* Enum encapsulating the possible card types.
*/
enum CardType {
UNDEFINED,
UNIT,
ARTIFACT
}
/**
* Struct encapsulating general card stats.
* @param HP Health Points.
* @param PWR Base Power.
* @param DEF Base Defense.
* @param SPD Base Attack Speed.
*/
struct Stats {
uint256 HP;
uint256 PWR;
uint256 DEF;
uint256 SPD;
}
/**
* Struct encapsulating information related to a unit base card.
* @param name Name of the unit.
* @param imageURI Unique resource identifier for the unit image.
* @param unitType Type of unit the base card is.
* @param stats Base stats of the unit.
* @param archetypes Archetypes related to the unit.
*/
struct Unit {
string name;
string imageURI;
uint16 unitType;
Stats stats;
uint16[] archetypes;
}
/**
* Struct encapsulating information related to an artifact base card.
* @param name Name of the artifact.
* @param imageURI Unique resource idenitifier for the artifact image.
* @param cardTier Base card tier of the artifact.
* @param archetypes Archetypes related to the artifact.
*/
struct Artifact {
string name;
string imageURI;
CardTier cardTier;
uint16[] archetypes;
}
/**
* Struct encapsulating information related to a base card.
* @param name Name of the base card, this will either be the name of the unit or the artifact.
* @param imageURI Unique resource identifier for the image, this will either be an image of a unit or an artifact.
* @param cardType Either an artifact or a unit.
* @param cardTier For artifacts this will be constant. For units, a tier will be determined upon mint.
* @param stats For artifacts all stats will be 0. For units, stats will be determined upon mint.
* @param archetypes Archetypes related to the underlying base card.
*/
struct BaseCard {
string name;
string imageURI;
CardType cardType;
CardTier cardTier;
uint16 unitType;
Stats stats;
uint16[] archetypes;
}
/**
* Struct encapsulating information related to a tokenized player card.
* @param baseCardId Base card identifier associated with the player card.
* @param serialNumber The number which indicates how many of this card existed at mint.
* @param level Level of the card.
* @param cardType Indicates if this card is an artifact or unit.
* @param cardTier For artifacts this will be constant. For units, a tier will be determined upon mint.
* @param unitType Type of unit associated with this card, an artifact will yield a `0` value.
* @param stats For artifacts all stats will be 0. For units, stats will be determined upon mint.
* @param archetypes Archetypes associated with the player card.
* @param abilityIds Abilities associated with the player card.
*/
struct PlayerCard {
uint256 baseCardId;
uint256 serialNumber;
uint256 level;
CardType cardType;
CardTier cardTier;
uint16 unitType;
Stats stats;
uint16[] archetypes;
uint256[3] abilityIds;
}
}
// lib/ERC721A-Upgradeable/contracts/interfaces/IERC721AUpgradeable.sol
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs
// lib/openzeppelin-contracts/contracts/utils/Pausable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.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 {
bool private _paused;
/**
* @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);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @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 {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @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());
}
}
// lib/solady/src/auth/OwnableRoles.sol
/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover and roles
/// may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `user`'s roles is updated to `roles`.
/// Each bit of `roles` represents whether the role is set.
event RolesUpdated(address indexed user, uint256 indexed roles);
/// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The role slot of `user` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
/// let roleSlot := keccak256(0x00, 0x20)
/// ```
/// This automatically ignores the upper bits of the `user` in case
/// they are not clean, as well as keep the `keccak256` under 32-bytes.
///
/// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Overwrite the roles directly without authorization guard.
function _setRoles(address user, uint256 roles) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Store the new value.
sstore(keccak256(0x0c, 0x20), roles)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
}
}
/// @dev Updates the roles directly without authorization guard.
/// If `on` is true, each set bit of `roles` will be turned on,
/// otherwise, each set bit of `roles` will be turned off.
function _updateRoles(address user, uint256 roles, bool on) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
let roleSlot := keccak256(0x0c, 0x20)
// Load the current value.
let current := sload(roleSlot)
// Compute the updated roles if `on` is true.
let updated := or(current, roles)
// Compute the updated roles if `on` is false.
// Use `and` to compute the intersection of `current` and `roles`,
// `xor` it with `current` to flip the bits in the intersection.
if iszero(on) { updated := xor(current, and(current, roles)) }
// Then, store the new value.
sstore(roleSlot, updated)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
}
}
/// @dev Grants the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn on.
function _grantRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, true);
}
/// @dev Removes the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn off.
function _removeRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, false);
}
/// @dev Throws if the sender does not have any of the `roles`.
function _checkRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Throws if the sender is not the owner,
/// and does not have any of the `roles`.
/// Checks for ownership first, then lazily checks for roles.
function _checkOwnerOrRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Throws if the sender does not have any of the `roles`,
/// and is not the owner.
/// Checks for roles first, then lazily checks for ownership.
function _checkRolesOrOwner(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
// We don't need to mask the values of `ordinals`, as Solidity
// cleans dirty upper bits when storing variables into memory.
roles := or(shl(mload(add(ordinals, i)), 1), roles)
}
}
}
/// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
/// @solidity memory-safe-assembly
assembly {
// Grab the pointer to the free memory.
ordinals := mload(0x40)
let ptr := add(ordinals, 0x20)
let o := 0
// The absence of lookup tables, De Bruijn, etc., here is intentional for
// smaller bytecode, as this function is not meant to be called on-chain.
for { let t := roles } 1 {} {
mstore(ptr, o)
// `shr` 5 is equivalent to multiplying by 0x20.
// Push back into the ordinals array if the bit is set.
ptr := add(ptr, shl(5, and(t, 1)))
o := add(o, 1)
t := shr(o, roles)
if iszero(t) { break }
}
// Store the length of `ordinals`.
mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
// Allocate the memory.
mstore(0x40, ptr)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
_removeRoles(user, roles);
}
/// @dev Allow the caller to remove their own roles.
/// If the caller does not have a role, then it will be an no-op for the role.
function renounceRoles(uint256 roles) public payable virtual {
_removeRoles(msg.sender, roles);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the roles of `user`.
function rolesOf(address user) public view virtual returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Load the stored value.
roles := sload(keccak256(0x0c, 0x20))
}
}
/// @dev Returns whether `user` has any of `roles`.
function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles != 0;
}
/// @dev Returns whether `user` has all of `roles`.
function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles == roles;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by an account with `roles`.
modifier onlyRoles(uint256 roles) virtual {
_checkRoles(roles);
_;
}
/// @dev Marks a function as only callable by the owner or by an account
/// with `roles`. Checks for ownership first, then lazily checks for roles.
modifier onlyOwnerOrRoles(uint256 roles) virtual {
_checkOwnerOrRoles(roles);
_;
}
/// @dev Marks a function as only callable by an account with `roles`
/// or the owner. Checks for roles first, then lazily checks for ownership.
modifier onlyRolesOrOwner(uint256 roles) virtual {
_checkRolesOrOwner(roles);
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ROLE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// IYKYK
uint256 internal constant _ROLE_0 = 1 << 0;
uint256 internal constant _ROLE_1 = 1 << 1;
uint256 internal constant _ROLE_2 = 1 << 2;
uint256 internal constant _ROLE_3 = 1 << 3;
uint256 internal constant _ROLE_4 = 1 << 4;
uint256 internal constant _ROLE_5 = 1 << 5;
uint256 internal constant _ROLE_6 = 1 << 6;
uint256 internal constant _ROLE_7 = 1 << 7;
uint256 internal constant _ROLE_8 = 1 << 8;
uint256 internal constant _ROLE_9 = 1 << 9;
uint256 internal constant _ROLE_10 = 1 << 10;
uint256 internal constant _ROLE_11 = 1 << 11;
uint256 internal constant _ROLE_12 = 1 << 12;
uint256 internal constant _ROLE_13 = 1 << 13;
uint256 internal constant _ROLE_14 = 1 << 14;
uint256 internal constant _ROLE_15 = 1 << 15;
uint256 internal constant _ROLE_16 = 1 << 16;
uint256 internal constant _ROLE_17 = 1 << 17;
uint256 internal constant _ROLE_18 = 1 << 18;
uint256 internal constant _ROLE_19 = 1 << 19;
uint256 internal constant _ROLE_20 = 1 << 20;
uint256 internal constant _ROLE_21 = 1 << 21;
uint256 internal constant _ROLE_22 = 1 << 22;
uint256 internal constant _ROLE_23 = 1 << 23;
uint256 internal constant _ROLE_24 = 1 << 24;
uint256 internal constant _ROLE_25 = 1 << 25;
uint256 internal constant _ROLE_26 = 1 << 26;
uint256 internal constant _ROLE_27 = 1 << 27;
uint256 internal constant _ROLE_28 = 1 << 28;
uint256 internal constant _ROLE_29 = 1 << 29;
uint256 internal constant _ROLE_30 = 1 << 30;
uint256 internal constant _ROLE_31 = 1 << 31;
uint256 internal constant _ROLE_32 = 1 << 32;
uint256 internal constant _ROLE_33 = 1 << 33;
uint256 internal constant _ROLE_34 = 1 << 34;
uint256 internal constant _ROLE_35 = 1 << 35;
uint256 internal constant _ROLE_36 = 1 << 36;
uint256 internal constant _ROLE_37 = 1 << 37;
uint256 internal constant _ROLE_38 = 1 << 38;
uint256 internal constant _ROLE_39 = 1 << 39;
uint256 internal constant _ROLE_40 = 1 << 40;
uint256 internal constant _ROLE_41 = 1 << 41;
uint256 internal constant _ROLE_42 = 1 << 42;
uint256 internal constant _ROLE_43 = 1 << 43;
uint256 internal constant _ROLE_44 = 1 << 44;
uint256 internal constant _ROLE_45 = 1 << 45;
uint256 internal constant _ROLE_46 = 1 << 46;
uint256 internal constant _ROLE_47 = 1 << 47;
uint256 internal constant _ROLE_48 = 1 << 48;
uint256 internal constant _ROLE_49 = 1 << 49;
uint256 internal constant _ROLE_50 = 1 << 50;
uint256 internal constant _ROLE_51 = 1 << 51;
uint256 internal constant _ROLE_52 = 1 << 52;
uint256 internal constant _ROLE_53 = 1 << 53;
uint256 internal constant _ROLE_54 = 1 << 54;
uint256 internal constant _ROLE_55 = 1 << 55;
uint256 internal constant _ROLE_56 = 1 << 56;
uint256 internal constant _ROLE_57 = 1 << 57;
uint256 internal constant _ROLE_58 = 1 << 58;
uint256 internal constant _ROLE_59 = 1 << 59;
uint256 internal constant _ROLE_60 = 1 << 60;
uint256 internal constant _ROLE_61 = 1 << 61;
uint256 internal constant _ROLE_62 = 1 << 62;
uint256 internal constant _ROLE_63 = 1 << 63;
uint256 internal constant _ROLE_64 = 1 << 64;
uint256 internal constant _ROLE_65 = 1 << 65;
uint256 internal constant _ROLE_66 = 1 << 66;
uint256 internal constant _ROLE_67 = 1 << 67;
uint256 internal constant _ROLE_68 = 1 << 68;
uint256 internal constant _ROLE_69 = 1 << 69;
uint256 internal constant _ROLE_70 = 1 << 70;
uint256 internal constant _ROLE_71 = 1 << 71;
uint256 internal constant _ROLE_72 = 1 << 72;
uint256 internal constant _ROLE_73 = 1 << 73;
uint256 internal constant _ROLE_74 = 1 << 74;
uint256 internal constant _ROLE_75 = 1 << 75;
uint256 internal constant _ROLE_76 = 1 << 76;
uint256 internal constant _ROLE_77 = 1 << 77;
uint256 internal constant _ROLE_78 = 1 << 78;
uint256 internal constant _ROLE_79 = 1 << 79;
uint256 internal constant _ROLE_80 = 1 << 80;
uint256 internal constant _ROLE_81 = 1 << 81;
uint256 internal constant _ROLE_82 = 1 << 82;
uint256 internal constant _ROLE_83 = 1 << 83;
uint256 internal constant _ROLE_84 = 1 << 84;
uint256 internal constant _ROLE_85 = 1 << 85;
uint256 internal constant _ROLE_86 = 1 << 86;
uint256 internal constant _ROLE_87 = 1 << 87;
uint256 internal constant _ROLE_88 = 1 << 88;
uint256 internal constant _ROLE_89 = 1 << 89;
uint256 internal constant _ROLE_90 = 1 << 90;
uint256 internal constant _ROLE_91 = 1 << 91;
uint256 internal constant _ROLE_92 = 1 << 92;
uint256 internal constant _ROLE_93 = 1 << 93;
uint256 internal constant _ROLE_94 = 1 << 94;
uint256 internal constant _ROLE_95 = 1 << 95;
uint256 internal constant _ROLE_96 = 1 << 96;
uint256 internal constant _ROLE_97 = 1 << 97;
uint256 internal constant _ROLE_98 = 1 << 98;
uint256 internal constant _ROLE_99 = 1 << 99;
uint256 internal constant _ROLE_100 = 1 << 100;
uint256 internal constant _ROLE_101 = 1 << 101;
uint256 internal constant _ROLE_102 = 1 << 102;
uint256 internal constant _ROLE_103 = 1 << 103;
uint256 internal constant _ROLE_104 = 1 << 104;
uint256 internal constant _ROLE_105 = 1 << 105;
uint256 internal constant _ROLE_106 = 1 << 106;
uint256 internal constant _ROLE_107 = 1 << 107;
uint256 internal constant _ROLE_108 = 1 << 108;
uint256 internal constant _ROLE_109 = 1 << 109;
uint256 internal constant _ROLE_110 = 1 << 110;
uint256 internal constant _ROLE_111 = 1 << 111;
uint256 internal constant _ROLE_112 = 1 << 112;
uint256 internal constant _ROLE_113 = 1 << 113;
uint256 internal constant _ROLE_114 = 1 << 114;
uint256 internal constant _ROLE_115 = 1 << 115;
uint256 internal constant _ROLE_116 = 1 << 116;
uint256 internal constant _ROLE_117 = 1 << 117;
uint256 internal constant _ROLE_118 = 1 << 118;
uint256 internal constant _ROLE_119 = 1 << 119;
uint256 internal constant _ROLE_120 = 1 << 120;
uint256 internal constant _ROLE_121 = 1 << 121;
uint256 internal constant _ROLE_122 = 1 << 122;
uint256 internal constant _ROLE_123 = 1 << 123;
uint256 internal constant _ROLE_124 = 1 << 124;
uint256 internal constant _ROLE_125 = 1 << 125;
uint256 internal constant _ROLE_126 = 1 << 126;
uint256 internal constant _ROLE_127 = 1 << 127;
uint256 internal constant _ROLE_128 = 1 << 128;
uint256 internal constant _ROLE_129 = 1 << 129;
uint256 internal constant _ROLE_130 = 1 << 130;
uint256 internal constant _ROLE_131 = 1 << 131;
uint256 internal constant _ROLE_132 = 1 << 132;
uint256 internal constant _ROLE_133 = 1 << 133;
uint256 internal constant _ROLE_134 = 1 << 134;
uint256 internal constant _ROLE_135 = 1 << 135;
uint256 internal constant _ROLE_136 = 1 << 136;
uint256 internal constant _ROLE_137 = 1 << 137;
uint256 internal constant _ROLE_138 = 1 << 138;
uint256 internal constant _ROLE_139 = 1 << 139;
uint256 internal constant _ROLE_140 = 1 << 140;
uint256 internal constant _ROLE_141 = 1 << 141;
uint256 internal constant _ROLE_142 = 1 << 142;
uint256 internal constant _ROLE_143 = 1 << 143;
uint256 internal constant _ROLE_144 = 1 << 144;
uint256 internal constant _ROLE_145 = 1 << 145;
uint256 internal constant _ROLE_146 = 1 << 146;
uint256 internal constant _ROLE_147 = 1 << 147;
uint256 internal constant _ROLE_148 = 1 << 148;
uint256 internal constant _ROLE_149 = 1 << 149;
uint256 internal constant _ROLE_150 = 1 << 150;
uint256 internal constant _ROLE_151 = 1 << 151;
uint256 internal constant _ROLE_152 = 1 << 152;
uint256 internal constant _ROLE_153 = 1 << 153;
uint256 internal constant _ROLE_154 = 1 << 154;
uint256 internal constant _ROLE_155 = 1 << 155;
uint256 internal constant _ROLE_156 = 1 << 156;
uint256 internal constant _ROLE_157 = 1 << 157;
uint256 internal constant _ROLE_158 = 1 << 158;
uint256 internal constant _ROLE_159 = 1 << 159;
uint256 internal constant _ROLE_160 = 1 << 160;
uint256 internal constant _ROLE_161 = 1 << 161;
uint256 internal constant _ROLE_162 = 1 << 162;
uint256 internal constant _ROLE_163 = 1 << 163;
uint256 internal constant _ROLE_164 = 1 << 164;
uint256 internal constant _ROLE_165 = 1 << 165;
uint256 internal constant _ROLE_166 = 1 << 166;
uint256 internal constant _ROLE_167 = 1 << 167;
uint256 internal constant _ROLE_168 = 1 << 168;
uint256 internal constant _ROLE_169 = 1 << 169;
uint256 internal constant _ROLE_170 = 1 << 170;
uint256 internal constant _ROLE_171 = 1 << 171;
uint256 internal constant _ROLE_172 = 1 << 172;
uint256 internal constant _ROLE_173 = 1 << 173;
uint256 internal constant _ROLE_174 = 1 << 174;
uint256 internal constant _ROLE_175 = 1 << 175;
uint256 internal constant _ROLE_176 = 1 << 176;
uint256 internal constant _ROLE_177 = 1 << 177;
uint256 internal constant _ROLE_178 = 1 << 178;
uint256 internal constant _ROLE_179 = 1 << 179;
uint256 internal constant _ROLE_180 = 1 << 180;
uint256 internal constant _ROLE_181 = 1 << 181;
uint256 internal constant _ROLE_182 = 1 << 182;
uint256 internal constant _ROLE_183 = 1 << 183;
uint256 internal constant _ROLE_184 = 1 << 184;
uint256 internal constant _ROLE_185 = 1 << 185;
uint256 internal constant _ROLE_186 = 1 << 186;
uint256 internal constant _ROLE_187 = 1 << 187;
uint256 internal constant _ROLE_188 = 1 << 188;
uint256 internal constant _ROLE_189 = 1 << 189;
uint256 internal constant _ROLE_190 = 1 << 190;
uint256 internal constant _ROLE_191 = 1 << 191;
uint256 internal constant _ROLE_192 = 1 << 192;
uint256 internal constant _ROLE_193 = 1 << 193;
uint256 internal constant _ROLE_194 = 1 << 194;
uint256 internal constant _ROLE_195 = 1 << 195;
uint256 internal constant _ROLE_196 = 1 << 196;
uint256 internal constant _ROLE_197 = 1 << 197;
uint256 internal constant _ROLE_198 = 1 << 198;
uint256 internal constant _ROLE_199 = 1 << 199;
uint256 internal constant _ROLE_200 = 1 << 200;
uint256 internal constant _ROLE_201 = 1 << 201;
uint256 internal constant _ROLE_202 = 1 << 202;
uint256 internal constant _ROLE_203 = 1 << 203;
uint256 internal constant _ROLE_204 = 1 << 204;
uint256 internal constant _ROLE_205 = 1 << 205;
uint256 internal constant _ROLE_206 = 1 << 206;
uint256 internal constant _ROLE_207 = 1 << 207;
uint256 internal constant _ROLE_208 = 1 << 208;
uint256 internal constant _ROLE_209 = 1 << 209;
uint256 internal constant _ROLE_210 = 1 << 210;
uint256 internal constant _ROLE_211 = 1 << 211;
uint256 internal constant _ROLE_212 = 1 << 212;
uint256 internal constant _ROLE_213 = 1 << 213;
uint256 internal constant _ROLE_214 = 1 << 214;
uint256 internal constant _ROLE_215 = 1 << 215;
uint256 internal constant _ROLE_216 = 1 << 216;
uint256 internal constant _ROLE_217 = 1 << 217;
uint256 internal constant _ROLE_218 = 1 << 218;
uint256 internal constant _ROLE_219 = 1 << 219;
uint256 internal constant _ROLE_220 = 1 << 220;
uint256 internal constant _ROLE_221 = 1 << 221;
uint256 internal constant _ROLE_222 = 1 << 222;
uint256 internal constant _ROLE_223 = 1 << 223;
uint256 internal constant _ROLE_224 = 1 << 224;
uint256 internal constant _ROLE_225 = 1 << 225;
uint256 internal constant _ROLE_226 = 1 << 226;
uint256 internal constant _ROLE_227 = 1 << 227;
uint256 internal constant _ROLE_228 = 1 << 228;
uint256 internal constant _ROLE_229 = 1 << 229;
uint256 internal constant _ROLE_230 = 1 << 230;
uint256 internal constant _ROLE_231 = 1 << 231;
uint256 internal constant _ROLE_232 = 1 << 232;
uint256 internal constant _ROLE_233 = 1 << 233;
uint256 internal constant _ROLE_234 = 1 << 234;
uint256 internal constant _ROLE_235 = 1 << 235;
uint256 internal constant _ROLE_236 = 1 << 236;
uint256 internal constant _ROLE_237 = 1 << 237;
uint256 internal constant _ROLE_238 = 1 << 238;
uint256 internal constant _ROLE_239 = 1 << 239;
uint256 internal constant _ROLE_240 = 1 << 240;
uint256 internal constant _ROLE_241 = 1 << 241;
uint256 internal constant _ROLE_242 = 1 << 242;
uint256 internal constant _ROLE_243 = 1 << 243;
uint256 internal constant _ROLE_244 = 1 << 244;
uint256 internal constant _ROLE_245 = 1 << 245;
uint256 internal constant _ROLE_246 = 1 << 246;
uint256 internal constant _ROLE_247 = 1 << 247;
uint256 internal constant _ROLE_248 = 1 << 248;
uint256 internal constant _ROLE_249 = 1 << 249;
uint256 internal constant _ROLE_250 = 1 << 250;
uint256 internal constant _ROLE_251 = 1 << 251;
uint256 internal constant _ROLE_252 = 1 << 252;
uint256 internal constant _ROLE_253 = 1 << 253;
uint256 internal constant _ROLE_254 = 1 << 254;
uint256 internal constant _ROLE_255 = 1 << 255;
}
// src/interfaces/IBaseCards.sol
/**
* @title IBaseCards
* @notice Interface for BaseCards.
*/
interface IBaseCards {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided as input.
*/
error ZeroAddress();
/**
* Thrown when an input array of zero length is provided.
*/
error ZeroLengthArray();
/**
* Thrown when invalid card attributes have been provided.
*/
error InvalidCardStats();
/**
* Thrown when an undefined Game.Unit type is provided.
*/
error UndefinedUnitType();
/**
* Thrown when an undefined archetype type is provided.
*/
error UndefinedArchetype();
/**
* Thrown when an invalid card ID is provided.
*/
error InvalidCardId();
/**
* Thrown when a duplicate archetype value is provided when adding base cards.
*/
error DuplicateArchetype();
/**
* Thrown when an undefined card type is provided when editing a base card.
*/
error UndefinedCardType();
/**
* Thrown when an invalid card tier is provided when editing a base card.
*/
error InvalidCardTier();
/**
* Thrown when a zero length name is provided when editing a base card.
*/
error EmptyName();
/**
* Thrown when a zero length image URI is provided when editing a base card.
*/
error EmptyImageURI();
/**
* Thrown when a unit card has invalid stats.
*/
error InvalidUnitStats();
/**
* Thrown when an undefined card tier is provided.
*/
error UndefinedCardTier();
/**
* Thrown when no name or image URI are provided when editing a card.
*/
error EmptyParameters();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Emitted when a new base card is added to the game.
* @param baseCardId Unique base card identifier.
* @param newBaseCard Information relating to the newly added base card.
*/
event BaseCardAdded(uint256 indexed baseCardId, Game.BaseCard newBaseCard);
/**
* Emitted when a base card is modified.
* @param baseCardId Unique base card identifier.
* @param oldBaseCard Old `Game.BaseCard` struct.
* @param newBaseCard New `Game.BaseCard` struct.
*/
event BaseCardUpdated(uint256 indexed baseCardId, Game.BaseCard oldBaseCard, Game.BaseCard newBaseCard);
/**
* Emitted when the image URI of a base card is modified.
* @param baseCardId Unique base card identifier.
* @param oldImageURI Old `imageURI` value.
* @param newImageURI New `imageURI` value.
*/
event BaseCardImageURIUpdated(uint256 indexed baseCardId, string oldImageURI, string newImageURI);
/**
* Emitted when the `Game.BaseCard.name` value is modified.
* @param baseCardId Unique base card identifier.
* @param oldName Old `Game.BaseCard.name` value.
* @param newName New `Game.BaseCard.name` value.
*/
event BaseCardNameUpdated(uint256 indexed baseCardId, string oldName, string newName);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to view the total number of base cards.
*/
function baseCardCount() external view returns (uint256);
/**
* Function used to add new base cards to the game.
* @param units Array of unit base cards to add.
* @param artifacts Array of artifact base cards to add.
*/
function addBaseCards(Game.Unit[] calldata units, Game.Artifact[] calldata artifacts) external;
/**
* Function used to edit a base card.
* @param baseCardId Unique base card identifier.
* @param newBaseCard Newly desired `Game.BaseCard` struct.
* @dev This function may only be called if tokenized versions of this card have never been minted.
*/
function editBaseCard(uint256 baseCardId, Game.BaseCard calldata newBaseCard) external;
/**
* Function used to modify the image URI of a base card.
* @param baseCardId Unique base card identifier.
* @param newName Newly desired `name` value.
* @param newImageURI Newly desired `imageURI` value.
*/
function setNameAndImageURI(uint256 baseCardId, string calldata newName, string calldata newImageURI) external;
/**
* Function used to view the `Game.BaseCard` struct for a given card identifier.
* @param baseCardId Unique base card idenitifer.
*/
function baseCards(uint256 baseCardId) external view returns (Game.BaseCard memory);
}
// src/interfaces/ICardForgeV2.sol
/**
* @title ICardForgeV2
* @notice Interface for CardForgeV2.
*/
interface ICardForgeV2 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided.
*/
error ZeroAddress();
/**
* Thrown when an input array of zero length is provided.
*/
error ZeroLengthArray();
/**
* Thrown when two input arrays differ in length.
*/
error ArrayLengthMismatch();
/**
* Thrown when a provided base card ID is not valid.
*/
error InvalidBaseCardId();
/**
* Thrown when the two provided player cards differ in tier.
*/
error CardTierMismatch();
/**
* Thrown when the caller does not own the provided player card identifiers.
*/
error CallerNotOwner();
/**
* Thrown when a base card identifier is provided twice.
*/
error DuplicateBaseCardId();
/**
* Thrown when the same tokenised player card is provided twice.
*/
error DuplicateCardId();
/**
* Thrown when the sum of the `weights` array does not equal 10_000.
*/
error InvalidWeightSum();
/**
* Thrown when the provided base cards are not unit types.
*/
error InvalidCardType();
/**
* Thrown when an undefined card tier is provided.
*/
error UndefinedCardTier();
/**
* Thrown when an invalid upgrade chance is provided.
*/
error InvalidUpgradeChance();
/**
* Thrown when the artifact ID being forged does not exist.
*/
error NonExistentCardId();
/**
* Thrown when the card attempting to be forged is not an artifact.
*/
error CardNotArtifact();
/**
* Thrown when attempting to re-use an already used nonce.
*/
error NonceUsed();
/**
* Thrown when the recovered signer doesn't match the expected signer.
*/
error SignerMismatch();
/**
* Thrown when the caller is not the origin.
*/
error CallerNotOrigin();
/**
* Thrown when a signature has expired.
*/
error DeadlinePassed();
/**
* Thrown when batch size exceeds the maximum.
*/
error OverMaxBatchSize();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Emitted when the forge rate of a card tier is updated.
* @param cardTier Tier of card whoms rate is being updated.
* @param oldUpgradeChance Old upgrade chance.
* @param newUpgradeChance New upgrade chance.
*/
event UpgradeChanceUpdated(Game.CardTier cardTier, uint256 oldUpgradeChance, uint256 newUpgradeChance);
/**
* Emitted when the `signer` address is updated.
* @param oldSigner Old `signer` address.
* @param newSigner New `signer` address.
*/
event SignerUpdated(address indexed oldSigner, address indexed newSigner);
/**
* Emitted when forge data is updated.
* @param baseCardIds The base card IDs that can be forged.
* @param weights Weightings associated with each `baseCardId` of `baseCardIds`.
*/
event ForgeDataUpdated(uint256[] baseCardIds, uint256[] weights);
/**
* Emitted when a card is reforged.
* @param user Reforge caller.
* @param signature Signed message digest.
* @param cardId Unique card identifier.
*/
event Reforged(address indexed user, bytes indexed signature, uint256 cardId);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to batch forge new unit cards. Forging requires that the provided card IDs are of the same tier.
* @param cardIds Array of unique game card identifiers.
* @dev Forging iterates over `cardIds` in batches of 2. E.g. [f0,f0,f1,f1,f2,f2]
*/
function forgeUnits(uint256[] calldata cardIds) external;
/**
* Function used to forge an artifact.
* @param baseCardId Unique base card identifier.
* @param nonce Unique nonce.
* @param signature Signed message digest.
*/
function forgeArtifact(uint256 baseCardId, uint256 nonce, bytes calldata signature) external;
/**
* Function used to reforge a card.
* @param cardId Unique card idenitifer.
* @param signature Signed message digest.
* @param deadline Signature expiry time.
*/
function reforge(uint256 cardId, bytes calldata signature, uint256 deadline) external;
/**
* Function used to set forge data relating to forgable cards and their respective weight.
* @param baseCardIds Array of base card identifiers that can be forged.
* @param weights Array of weightings associated with each base card.
*/
function setForgeData(uint256[] calldata baseCardIds, uint256[] calldata weights) external;
/**
* Function used to set a new upgrade chance for a specified card tier.
* @param tier Card Tier to update the upgrade chance for.
* @param chance New upgrade chance for the provided tier.
*/
function setUpgradeChance(Game.CardTier tier, uint256 chance) external;
/**
* Function used to batch set forge upgrade chances.
* @param chances Array of upgrade chances for each valid card tier.
*/
function setUpgradeChances(uint256[] calldata chances) external;
/**
* Function used to set a new `signer` address.
* @param newSigner New `signer` address value.
*/
function setSigner(address newSigner) external;
/**
* Function used to toggle the paused state of the contract.
*/
function togglePause() external;
/**
* Function used to view the upgrade chances for all card tiers ordered from C->SSS.
*/
function upgradeChances() external view returns (uint256[] memory);
/**
* Function used to view the version of the contract.
*/
function version() external pure returns (string memory);
}
// src/interfaces/IGameCards.sol
/**
* @title IGameCards
* @notice Interface for GameCards.
*/
interface IGameCards is IERC721AUpgradeable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided.
*/
error ZeroAddress();
/**
* Thrown when an input array of zero length is provided.
*/
error ZeroLengthArray();
/**
* Thrown when trying to access data for a non-existent token ID.
*/
error NonExistentTokenId();
/**
* Thrown when the caller is not the owner of the card.
*/
error CallerNotOwner();
/**
* Thrown when the specified level does not match the expected level.
*/
error CardLevelMismatch();
/**
* Thrown when the recovered signer does not match the expected signer.
*/
error SignerMismatch();
/**
* Thrown when an invalid card level is provided.
*/
error InvalidCardLevel();
/**
* Thrown when an invalid maximum card level is provided.
*/
error InvalidMaxLevel();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Emitted when a new player card is defined.
* @param tokenId Unique token identifier.
* @param newPlayerCard Information relating to the newly defined player card.
*/
event PlayerCardDefined(uint256 indexed tokenId, Game.PlayerCard newPlayerCard);
/**
* Emitted when the `Seeder` contract is updated.
* @param oldSeeder Old `Seeder` contract address.
* @param newSeeder New `Seeder` contract address.
*/
event SeederUpdated(address oldSeeder, address newSeeder);
/**
* Emitted when the `Abilities` contract is updated.
* @param oldAbilities Old `Abilities` contract address.
* @param newAbilities New `Abilities` contract address.
*/
event AbilitiesUpdated(address oldAbilities, address newAbilities);
/**
* Emitted when the `MetadataRenderer` contract is updated.
* @param oldMetadataRenderer Old `MetadataRenderer` contract address.
* @param newMetadataRenderer New `MetadataRenderer` contract address.
*/
event MetadataRendererUpdated(address oldMetadataRenderer, address newMetadataRenderer);
/**
* Emitted when the `signer` address is updated.
* @param oldSigner Old `signer` address.
* @param newSigner New `signer` address.
*/
event SignerUpdated(address indexed oldSigner, address indexed newSigner);
/**
* Emitted when the `baseCards` address is updated.
* @param oldBaseCards Old `baseCards` address.
* @param newBaseCards New `baseCards` address.
*/
event BaseCardsUpdated(address oldBaseCards, address newBaseCards);
/**
* Emitted when a player card is leveled.
* @param tokenId Unique card identifier.
* @param oldLevel Old card level.
* @param newLevel New card level.
*/
event LevelUp(uint256 indexed tokenId, uint256 oldLevel, uint256 newLevel);
/**
* Emitted when the maximum card level is updated.
* @param oldMaxLevel Old maximum card level.
* @param newMaxLevel New maximum card level.
*/
event MaxCardLevelUpdated(uint256 oldMaxLevel, uint256 newMaxLevel);
/**
* Emitted when level stat modifiers are updated.
* @param level Stat level being modified.
* @param oldStatModifiers Old stat modifiers for `level`.
* @param newStatModifiers New stat modifiers for `level`.
*/
event StatModifiersUpdated(uint256 indexed level, Game.Stats oldStatModifiers, Game.Stats newStatModifiers);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to view the total number of derivative base cards that have been minted.
* @param baseCardId Unique base card identifier.
*/
function serialNumbers(uint256 baseCardId) external view returns (uint256);
/**
* Function used to initialize the Cards contract.
* @param _owner Contract owner.
* @param _gameMaster Designed Game Master.
* @param _signer Signer address.
* @param _seeder Seeder contract.
* @param _baseCards BaseCards contract.
* @param _abilities Abilities contract.
* @param _metadataRenderer Metadata renderer contract.
* @param _blastGovernor Blast Governor contract.
*/
function initialize(
address _owner,
address _gameMaster,
address _signer,
address _seeder,
address _baseCards,
address _abilities,
address _metadataRenderer,
address _blastGovernor
)
external;
/**
* Function used to mint new cards to the receiver.
* @param cardIds Unique card identifiers to mint.
* @param tierWeights Weightings associated with rolling a specific tier of card.
* @param receiver Address to mint the new cards to.
*/
function mintCards(uint256[] calldata cardIds, uint256[6] calldata tierWeights, address receiver) external;
/**
* Function used to incinerate a list of cards.
* @param tokenIds Array of card identifiers.
*/
function incinerate(uint256[] calldata tokenIds) external;
/**
* Function used to level up a card.
* @param tokenId Unique card identifier.
* @param newLevel Expected new level of the card.
* @param signature Signed message digest.
*/
function levelUpCard(uint256 tokenId, uint256 newLevel, bytes calldata signature) external;
/**
* Function used to set a new `Seeder` value.
* @param newSeeder New `Seeder` contract address.
*/
function setSeeder(address newSeeder) external;
/**
* Function used to set a new `BaseCards` value.
* @param newBaseCards New `BaseCards` contract address.
*/
function setBaseCards(address newBaseCards) external;
/**
* Function used to set a new `Abilities` value.
* @param newAbilities New `Abilities` contract address.
*/
function setAbilities(address newAbilities) external;
/**
* Function used to set a new `MetadataRenderer` value.
* @param newMetadataRenderer New `MetadataRenderer` contract address.
*/
function setMetadataRenderer(address newMetadataRenderer) external;
/**
* Function used to set a new `signer` address.
* @param newSigner New `signer` address value.
*/
function setSigner(address newSigner) external;
/**
* Function used to set stat modifiers for a specified card level.
* @param level Card level to set stat modifiers for.
* @param modifiers New stat modifiers for `level`.
*/
function setCardLevelModifiers(uint256 level, Game.Stats calldata modifiers) external;
/**
* Function used to set a new maximum card level.
* @param newMaxLevel New maximum card level value.
*/
function setMaxCardLevel(uint256 newMaxLevel) external;
/**
* Function used to view the `Game.PlayerCard` struct for a given token idenitifer.
* @param tokenId Unique token identifier.
*/
function playerCards(uint256 tokenId) external view returns (Game.PlayerCard memory);
/**
* Function used to view the current stat modifiers of a given card level.
* @param cardLevel Card level to check modifiers for.
*/
function statModifiers(uint256 cardLevel) external view returns (Game.Stats memory);
}
// src/CardForgeV2.sol
/**
* @title CardForgeV2
* @notice This contract handles all functionality related to card forging. Units can be forged by incinerating
* two equivalent unit cards of the same tier whilst artifacts can be forged using items. Version 2 supports multi-card
* unit forging.
*/
contract CardForgeV2 is ICardForgeV2, OwnableRoles, Pausable {
using ECDSA for bytes32;
uint256 private constant _WEIGHT_SUM = 10_000;
uint256 private constant _MAX_CHANCE = 10_000;
uint256 private constant _MAX_BATCH_SIZE = 20;
IBlast public immutable BLAST = IBlast(0x4300000000000000000000000000000000000002);
uint256[] public forgeCards;
uint256[] public cardWeights;
address public signer;
ISeeder public seeder;
IGameCards public gameCards;
IBaseCards public baseCards;
mapping(Game.CardTier cardTier => uint256 chance) private _upgradeChances;
mapping(uint256 nonce => bool isUsed) public nonceUsed;
constructor(
address _gameMaster,
address _signer,
address _seeder,
address _gameCards,
address _baseCards,
address _blastGovernor
) {
if (
_gameMaster == address(0) || _signer == address(0) || _seeder == address(0) || _gameCards == address(0)
|| _baseCards == address(0) || _blastGovernor == address(0)
) revert ZeroAddress();
BLAST.configureClaimableGas();
BLAST.configureGovernor({ _governor: _blastGovernor });
_initializeOwner({ newOwner: msg.sender });
_grantRoles({ user: _gameMaster, roles: AccessRoles.GAME_MASTER_ROLE });
signer = _signer;
seeder = ISeeder(_seeder);
gameCards = IGameCards(_gameCards);
baseCards = IBaseCards(_baseCards);
}
/**
* Function used to forge multiple units at once.
* @param cardIds Array of unique game card identifiers.
*/
function forgeUnits(uint256[] calldata cardIds) external whenNotPaused {
// Checks: Ensure no smart contracts can forge units.
if (msg.sender != tx.origin) revert CallerNotOrigin();
// Checks: Ensure the `cardIds` array is non-zero length.
if (cardIds.length == 0) revert ZeroLengthArray();
// Checks: Ensure an even number of card IDs have been provided.
if (cardIds.length % 2 != 0) revert ArrayLengthMismatch();
uint256 ephemeralSeed = seeder.getAndUpdateGameSeed();
uint256 iterations = cardIds.length / 2;
if (iterations > _MAX_BATCH_SIZE) revert OverMaxBatchSize();
uint256[] memory baseCardIds = new uint256[](iterations);
Game.CardTier[] memory cardTiers = new Game.CardTier[](iterations);
// Validate ownership and eligibility of each forge batch.
// This loop iterates through `cardIds` in batches of 2. E.g. [0,0,1,1,2,2]
for (uint256 i = 0; i < iterations; i++) {
uint256 cardIdOne = cardIds[i * 2];
uint256 cardIdTwo = cardIds[i * 2 + 1];
// Checks: Ensure `msg.sender` owns both cards.
if (msg.sender != gameCards.ownerOf({ tokenId: cardIdOne })) revert CallerNotOwner();
if (msg.sender != gameCards.ownerOf({ tokenId: cardIdTwo })) revert CallerNotOwner();
Game.PlayerCard memory cardA = gameCards.playerCards({ tokenId: cardIdOne });
Game.PlayerCard memory cardB = gameCards.playerCards({ tokenId: cardIdTwo });
// Checks: Ensure both cards are equivalent in tier.
if (cardA.cardTier != cardB.cardTier) revert CardTierMismatch();
// Checks: Ensure both cards are unit cards.
if (cardA.cardType != Game.CardType.UNIT || cardB.cardType != Game.CardType.UNIT) revert InvalidCardType();
uint256 upgradeChance = _upgradeChances[cardA.cardTier];
// Checks: Ensure the forge rate is non-zero.
if (upgradeChance == 0) revert InvalidUpgradeChance();
uint256 upgradeRoll = uint256(keccak256(abi.encodePacked(ephemeralSeed, i))) % _MAX_CHANCE + 1;
uint256 characterRoll = uint256(keccak256(abi.encodePacked(upgradeRoll, i))) % _WEIGHT_SUM + 1;
// If the player has rolled an upgrade, allocate the new card tier to be a tier above
// their provided card tiers assuming the provided card isn't SSS. Otherwise, mint a card of the same tier.
if (upgradeRoll <= upgradeChance) {
cardTiers[i] =
cardA.cardTier == Game.CardTier.SSS ? Game.CardTier.SSS : Game.CardTier(uint256(cardA.cardTier) + 1);
} else {
cardTiers[i] = cardA.cardTier;
}
uint256 cumulativeWeight = 0;
for (uint256 j = 0; j < cardWeights.length; j++) {
cumulativeWeight += cardWeights[j];
if (characterRoll <= cumulativeWeight) {
baseCardIds[i] = forgeCards[j];
break;
}
}
}
// Burn all the provided card IDs. If duplicate card IDs have been provided, this call will revert.
gameCards.incinerate({ tokenIds: cardIds });
for (uint256 i = 0; i < baseCardIds.length; i++) {
uint256[] memory cardId = new uint256[](1);
cardId[0] = baseCardIds[i];
gameCards.mintCards({
cardIds: cardId,
tierWeights: _getTierWeightsArray(cardTiers[i]),
receiver: msg.sender
});
}
}
/**
* @inheritdoc ICardForgeV2
*/
function forgeArtifact(uint256 baseCardId, uint256 nonce, bytes calldata signature) external whenNotPaused {
if (baseCardId == 0 || baseCardId > baseCards.baseCardCount()) revert NonExistentCardId();
if (baseCards.baseCards(baseCardId).cardType != Game.CardType.ARTIFACT) revert CardNotArtifact();
bytes32 digest = keccak256(abi.encodePacked(msg.sender, baseCardId, nonce, "FA")).toEthSignedMessageHash();
if (digest.recover(signature) != signer) revert SignerMismatch();
if (nonceUsed[nonce]) revert NonceUsed();
nonceUsed[nonce] = true;
uint256[] memory ids = new uint256[](1);
ids[0] = baseCardId;
uint256[6] memory weights;
gameCards.mintCards({ cardIds: ids, tierWeights: weights, receiver: msg.sender });
}
/**
* @inheritdoc ICardForgeV2
*/
function reforge(uint256 cardId, bytes calldata signature, uint256 deadline) external whenNotPaused {
if (msg.sender != gameCards.ownerOf({ tokenId: cardId })) revert CallerNotOwner();
if (block.timestamp > deadline) revert DeadlinePassed();
bytes32 digest = keccak256(abi.encodePacked(msg.sender, cardId, deadline, "RF")).toEthSignedMessageHash();
if (digest.recover(signature) != signer) revert SignerMismatch();
Game.PlayerCard memory card = gameCards.playerCards({ tokenId: cardId });
if (card.cardType != Game.CardType.UNIT) revert InvalidCardType();
uint256[] memory cardIds = new uint256[](1);
cardIds[0] = cardId;
gameCards.incinerate({ tokenIds: cardIds });
uint256[] memory ids = new uint256[](1);
ids[0] = card.baseCardId;
uint256[6] memory weights;
weights[uint256(card.cardTier) - 1] = 10_000;
gameCards.mintCards({ cardIds: ids, tierWeights: weights, receiver: msg.sender });
emit Reforged({ user: msg.sender, signature: signature, cardId: cardId });
}
/**
* @inheritdoc ICardForgeV2
*/
function setForgeData(
uint256[] calldata baseCardIds,
uint256[] calldata weights
)
external
onlyRoles(AccessRoles.GAME_MASTER_ROLE)
{
_validateInputs(baseCardIds, weights);
forgeCards = baseCardIds;
cardWeights = weights;
emit ForgeDataUpdated(baseCardIds, cardWeights);
}
/**
* @inheritdoc ICardForgeV2
*/
function setUpgradeChance(
Game.CardTier cardTier,
uint256 chance
)
external
onlyRoles(AccessRoles.GAME_MASTER_ROLE)
{
if (cardTier == Game.CardTier.UNDEFINED) revert UndefinedCardTier();
if (chance == 0 || chance > _MAX_CHANCE) revert InvalidUpgradeChance();
uint256 oldUpgradeChance = _upgradeChances[cardTier];
_upgradeChances[cardTier] = chance;
emit UpgradeChanceUpdated(cardTier, oldUpgradeChance, chance);
}
/**
* @inheritdoc ICardForgeV2
*/
function setUpgradeChances(uint256[] calldata chances) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
/// @dev `6` because all chances from C->SSS need to be provided.
if (chances.length != 6) revert ArrayLengthMismatch();
for (uint256 i = 0; i < chances.length; i++) {
uint256 chance = chances[i];
if (chance == 0 || chance > _MAX_CHANCE) revert InvalidUpgradeChance();
/// @dev Add `1` to skip the `Game.CardTier.UNDEFINED` value.
Game.CardTier cardTier = Game.CardTier(i + 1);
uint256 oldUpgradeChance = _upgradeChances[cardTier];
_upgradeChances[cardTier] = chance;
emit UpgradeChanceUpdated(cardTier, oldUpgradeChance, chance);
}
}
/**
* @inheritdoc ICardForgeV2
*/
function setSigner(address newSigner) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
if (newSigner == address(0)) revert ZeroAddress();
address oldSigner = signer;
signer = newSigner;
emit SignerUpdated(oldSigner, newSigner);
}
/**
* @inheritdoc ICardForgeV2
*/
function togglePause() external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
paused() ? _unpause() : _pause();
}
/**
* @inheritdoc ICardForgeV2
*/
function version() external pure returns (string memory) {
return "2.0.0";
}
/**
* @inheritdoc ICardForgeV2
*/
function upgradeChances() external view returns (uint256[] memory) {
uint256[] memory chances = new uint256[](6);
for (uint256 i = 0; i < chances.length; i++) {
/// @dev Add `1` to skip the `Game.CardTier.UNDEFINED` value.
chances[i] = _upgradeChances[Game.CardTier(i + 1)];
}
return chances;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL LOGIC */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to validate that:
* 1. `ids` and `weights` are equal in length.
* 2. `ids` only contains valid base card identifiers.
* 3. `ids` contains no duplicate entries.
* 4. `weights` sum equals `_WEIGHT_SUM` (10_000).
*/
function _validateInputs(uint256[] memory baseCardIds, uint256[] memory weights) internal view {
if (baseCardIds.length != weights.length) revert ArrayLengthMismatch();
if (baseCardIds.length == 0) revert ZeroLengthArray();
uint256 maxCardId = baseCards.baseCardCount();
uint256 weightSum = 0;
uint256 dupes = 0;
for (uint256 i = 0; i < baseCardIds.length; i++) {
uint256 baseCardId = baseCardIds[i];
if (baseCardId == 0 || baseCardId > maxCardId) revert InvalidBaseCardId();
if (dupes >> baseCardId & 1 == 1) revert DuplicateBaseCardId();
dupes |= 1 << baseCardId;
weightSum += weights[i];
}
if (weightSum != _WEIGHT_SUM) revert InvalidWeightSum();
}
/**
* Function used to return an array that guarantees a card tier upgrade.
* @param cardTier Tier of the newly forged card.
*/
function _getTierWeightsArray(Game.CardTier cardTier) internal pure returns (uint256[6] memory tierWeights) {
uint256 tierIdx = cardTier == Game.CardTier.SSS ? 5 : uint256(cardTier) - 1;
tierWeights[tierIdx] = _WEIGHT_SUM;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_gameMaster","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_seeder","type":"address"},{"internalType":"address","name":"_gameCards","type":"address"},{"internalType":"address","name":"_baseCards","type":"address"},{"internalType":"address","name":"_blastGovernor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"CallerNotOrigin","type":"error"},{"inputs":[],"name":"CallerNotOwner","type":"error"},{"inputs":[],"name":"CardNotArtifact","type":"error"},{"inputs":[],"name":"CardTierMismatch","type":"error"},{"inputs":[],"name":"DeadlinePassed","type":"error"},{"inputs":[],"name":"DuplicateBaseCardId","type":"error"},{"inputs":[],"name":"DuplicateCardId","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InvalidBaseCardId","type":"error"},{"inputs":[],"name":"InvalidCardType","type":"error"},{"inputs":[],"name":"InvalidUpgradeChance","type":"error"},{"inputs":[],"name":"InvalidWeightSum","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NonExistentCardId","type":"error"},{"inputs":[],"name":"NonceUsed","type":"error"},{"inputs":[],"name":"OverMaxBatchSize","type":"error"},{"inputs":[],"name":"SignerMismatch","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UndefinedCardTier","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroLengthArray","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"baseCardIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"ForgeDataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":"user","type":"address"},{"indexed":true,"internalType":"bytes","name":"signature","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"cardId","type":"uint256"}],"name":"Reforged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":true,"internalType":"address","name":"newSigner","type":"address"}],"name":"SignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum Game.CardTier","name":"cardTier","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"oldUpgradeChance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newUpgradeChance","type":"uint256"}],"name":"UpgradeChanceUpdated","type":"event"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseCards","outputs":[{"internalType":"contract IBaseCards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"cardWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseCardId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"forgeArtifact","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"forgeCards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"cardIds","type":"uint256[]"}],"name":"forgeUnits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gameCards","outputs":[{"internalType":"contract IGameCards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"nonceUsed","outputs":[{"internalType":"bool","name":"isUsed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cardId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"reforge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seeder","outputs":[{"internalType":"contract ISeeder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"baseCardIds","type":"uint256[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"setForgeData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Game.CardTier","name":"cardTier","type":"uint8"},{"internalType":"uint256","name":"chance","type":"uint256"}],"name":"setUpgradeChance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"chances","type":"uint256[]"}],"name":"setUpgradeChances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"togglePause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"upgradeChances","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
60a060405273430000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff168152503480156200005857600080fd5b5060405162004a6c38038062004a6c83398181016040528101906200007e9190620005e9565b60008060006101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161480620001005750600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b80620001385750600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80620001705750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b80620001a85750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80620001e05750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b1562000218576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60805173ffffffffffffffffffffffffffffffffffffffff16634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200026357600080fd5b505af115801562000278573d6000803e3d6000fd5b5050505060805173ffffffffffffffffffffffffffffffffffffffff1663eb864698826040518263ffffffff1660e01b8152600401620002b9919062000696565b600060405180830381600087803b158015620002d457600080fd5b505af1158015620002e9573d6000803e3d6000fd5b50505050620002fe336200042160201b60201c565b620003118660016200050760201b60201c565b84600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050505050620006b3565b620004316200051f60201b60201c565b15620004af577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278054156200046e57630dc149f06000526004601cfd5b8160601b60601c9150811560ff1b821781558160007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35062000504565b8060601b60601c9050807fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35b50565b6200051b828260016200052460201b60201c565b5050565b600090565b638b78c6d8600c52826000526020600c208054838117836200054857848216821890505b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005b18262000584565b9050919050565b620005c381620005a4565b8114620005cf57600080fd5b50565b600081519050620005e381620005b8565b92915050565b60008060008060008060c087890312156200060957620006086200057f565b5b60006200061989828a01620005d2565b96505060206200062c89828a01620005d2565b95505060406200063f89828a01620005d2565b94505060606200065289828a01620005d2565b93505060806200066589828a01620005d2565b92505060a06200067889828a01620005d2565b9150509295509295509295565b6200069081620005a4565b82525050565b6000602082019050620006ad600083018462000685565b92915050565b60805161439d620006cf6000396000611dc3015261439d6000f3fe6080604052600436106101e35760003560e01c8063715018a611610102578063aaec03f911610095578063f04e283e11610064578063f04e283e14610658578063f2fde38b14610674578063f7a2e7a614610690578063fee81cf4146106b9576101e3565b8063aaec03f9146105c2578063bad956a0146105ed578063c4ae316814610618578063d7be9db31461062f576101e3565b80637e941a0d116100d15780637e941a0d146105065780638da5cb5b1461052f57806394d0d3a61461055a57806397d7577614610597576101e3565b8063715018a61461046b57806372dcb18a14610475578063788986741461049e5780637afb9b1d146104db576101e3565b80633d5381101161017a57806354fd4d501161014957806354fd4d50146103c15780635c975abb146103ec578063684931ed146104175780636c19e78314610442576101e3565b80633d538110146103355780634a4ee7b11461035e578063514e62fc1461037a57806354d1f13d146103b7576101e3565b8063238ac933116101b6578063238ac9331461028657806325692962146102b15780632de94807146102bb57806338c73fd4146102f8576101e3565b8063183a4f6e146101e85780631c10893f146102045780631cd64df41461022057806320b4eb021461025d575b600080fd5b61020260048036038101906101fd9190612e98565b6106f6565b005b61021e60048036038101906102199190612f23565b610703565b005b34801561022c57600080fd5b5061024760048036038101906102429190612f23565b610719565b6040516102549190612f7e565b60405180910390f35b34801561026957600080fd5b50610284600480360381019061027f9190612ffe565b610730565b005b34801561029257600080fd5b5061029b610bb7565b6040516102a89190613081565b60405180910390f35b6102b9610bdd565b005b3480156102c757600080fd5b506102e260048036038101906102dd919061309c565b610c31565b6040516102ef91906130d8565b60405180910390f35b34801561030457600080fd5b5061031f600480360381019061031a9190612e98565b610c4c565b60405161032c91906130d8565b60405180910390f35b34801561034157600080fd5b5061035c60048036038101906103579190613149565b610c70565b005b61037860048036038101906103739190612f23565b611854565b005b34801561038657600080fd5b506103a1600480360381019061039c9190612f23565b61186a565b6040516103ae9190612f7e565b60405180910390f35b6103bf611882565b005b3480156103cd57600080fd5b506103d66118be565b6040516103e39190613226565b60405180910390f35b3480156103f857600080fd5b506104016118fb565b60405161040e9190612f7e565b60405180910390f35b34801561042357600080fd5b5061042c611911565b60405161043991906132a7565b60405180910390f35b34801561044e57600080fd5b506104696004803603810190610464919061309c565b611937565b005b610473611a6f565b005b34801561048157600080fd5b5061049c60048036038101906104979190613149565b611a83565b005b3480156104aa57600080fd5b506104c560048036038101906104c09190612e98565b611c30565b6040516104d291906130d8565b60405180910390f35b3480156104e757600080fd5b506104f0611c54565b6040516104fd91906132e3565b60405180910390f35b34801561051257600080fd5b5061052d600480360381019061052891906132fe565b611c7a565b005b34801561053b57600080fd5b50610544611d78565b6040516105519190613081565b60405180910390f35b34801561056657600080fd5b50610581600480360381019061057c9190612e98565b611da1565b60405161058e9190612f7e565b60405180910390f35b3480156105a357600080fd5b506105ac611dc1565b6040516105b991906133a0565b60405180910390f35b3480156105ce57600080fd5b506105d7611de5565b6040516105e49190613479565b60405180910390f35b3480156105f957600080fd5b50610602611ed1565b60405161060f91906134bc565b60405180910390f35b34801561062457600080fd5b5061062d611ef7565b005b34801561063b57600080fd5b50610656600480360381019061065191906134d7565b611f27565b005b610672600480360381019061066d919061309c565b61253e565b005b61068e6004803603810190610689919061309c565b61257f565b005b34801561069c57600080fd5b506106b760048036038101906106b29190613570565b6125a9565b005b3480156106c557600080fd5b506106e060048036038101906106db919061309c565b612712565b6040516106ed91906130d8565b60405180910390f35b610700338261272d565b50565b61070b61273d565b6107158282612775565b5050565b6000818261072685610c31565b1614905092915050565b610738612785565b60008414806107d65750600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d391906135c5565b84115b1561080d576040517f0d4a929c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002808111156108205761081f6135f2565b5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663abb05174866040518263ffffffff1660e01b815260040161087b91906130d8565b600060405180830381865afa158015610898573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906108c19190613a05565b6040015160028111156108d7576108d66135f2565b5b1461090e576040517fdbbad12800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061094333868660405160200161092893929190613b0e565b604051602081830303815290604052805190602001206127c6565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166109d584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050836127f890919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614610a22576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6008600085815260200190815260200160002060009054906101000a900460ff1615610a7a576040517f1f6d5aef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600086815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600167ffffffffffffffff811115610ac357610ac2613626565b5b604051908082528060200260200182016040528015610af15781602001602082028036833780820191505090505b5090508581600081518110610b0957610b08613b56565b5b602002602001018181525050610b1d612dc2565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca38383336040518463ffffffff1660e01b8152600401610b7c93929190613c09565b600060405180830381600087803b158015610b9657600080fd5b505af1158015610baa573d6000803e3d6000fd5b5050505050505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610be7612893565b67ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b6000638b78c6d8600c52816000526020600c20549050919050565b60018181548110610c5c57600080fd5b906000526020600020016000915090505481565b610c78612785565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cdd576040517fe02c6ccf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008282905003610d1a576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600283839050610d2c9190613c77565b14610d63576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663055877756040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df891906135c5565b90506000600284849050610e0c9190613cd7565b90506014811115610e49576040517f1afb23e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115610e6557610e64613626565b5b604051908082528060200260200182016040528015610e935781602001602082028036833780820191505090505b50905060008267ffffffffffffffff811115610eb257610eb1613626565b5b604051908082528060200260200182016040528015610ee05781602001602082028036833780820191505090505b50905060005b8381101561165f5760008787600284610eff9190613d08565b818110610f0f57610f0e613b56565b5b905060200201359050600088886001600286610f2b9190613d08565b610f359190613d4a565b818110610f4557610f44613b56565b5b905060200201359050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610fa991906130d8565b602060405180830381865afa158015610fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fea9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461104e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e826040518263ffffffff1660e01b81526004016110a991906130d8565b602060405180830381865afa1580156110c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ea9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461114e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f846040518263ffffffff1660e01b81526004016111ab91906130d8565b600060405180830381865afa1580156111c8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906111f19190613f6e565b90506000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f846040518263ffffffff1660e01b815260040161125091906130d8565b600060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906112969190613f6e565b9050806080015160068111156112af576112ae6135f2565b5b826080015160068111156112c6576112c56135f2565b5b146112fd576040517f41dc2d2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016002811115611311576113106135f2565b5b82606001516002811115611328576113276135f2565b5b14158061135e575060016002811115611344576113436135f2565b5b8160600151600281111561135b5761135a6135f2565b5b14155b15611395576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060076000846080015160068111156113b2576113b16135f2565b5b60068111156113c4576113c36135f2565b5b81526020019081526020016000205490506000810361140f576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060016127108c89604051602001611429929190613fb7565b6040516020818303038152906040528051906020012060001c61144c9190613c77565b6114569190613d4a565b905060006001612710838a604051602001611472929190613fb7565b6040516020818303038152906040528051906020012060001c6114959190613c77565b61149f9190613d4a565b905082821161155e576006808111156114bb576114ba6135f2565b5b856080015160068111156114d2576114d16135f2565b5b14611511576001856080015160068111156114f0576114ef6135f2565b5b6114fa9190613d4a565b600681111561150c5761150b6135f2565b5b611514565b60065b89898151811061152757611526613b56565b5b60200260200101906006811115611541576115406135f2565b5b90816006811115611555576115546135f2565b5b815250506115a9565b846080015189898151811061157657611575613b56565b5b602002602001019060068111156115905761158f6135f2565b5b908160068111156115a4576115a36135f2565b5b815250505b6000805b60028054905081101561164357600281815481106115ce576115cd613b56565b5b9060005260206000200154826115e49190613d4a565b9150818311611630576001818154811061160157611600613b56565b5b90600052602060002001548c8b8151811061161f5761161e613b56565b5b602002602001018181525050611643565b808061163b90613fe3565b9150506115ad565b505050505050505050808061165790613fe3565b915050610ee6565b50600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cf46fd0187876040518363ffffffff1660e01b81526004016116bd929190614095565b600060405180830381600087803b1580156116d757600080fd5b505af11580156116eb573d6000803e3d6000fd5b5050505060005b825181101561184b576000600167ffffffffffffffff81111561171857611717613626565b5b6040519080825280602002602001820160405280156117465781602001602082028036833780820191505090505b50905083828151811061175c5761175b613b56565b5b60200260200101518160008151811061177857611777613b56565b5b602002602001018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca3826117e68686815181106117d9576117d8613b56565b5b602002602001015161289e565b336040518463ffffffff1660e01b815260040161180593929190613c09565b600060405180830381600087803b15801561181f57600080fd5b505af1158015611833573d6000803e3d6000fd5b5050505050808061184390613fe3565b9150506116f2565b50505050505050565b61185c61273d565b611866828261272d565b5050565b6000808261187785610c31565b161415905092915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b60606040518060400160405280600581526020017f322e302e30000000000000000000000000000000000000000000000000000000815250905090565b60008060009054906101000a900460ff16905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600161194281612921565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119a8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb60405160405180910390a3505050565b611a7761273d565b611a81600061294a565b565b6001611a8e81612921565b60068383905014611acb576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b83839050811015611c2a576000848483818110611aee57611aed613b56565b5b9050602002013590506000811480611b07575061271081115b15611b3e576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600183611b4d9190613d4a565b6006811115611b5f57611b5e6135f2565b5b9050600060076000836006811115611b7a57611b796135f2565b5b6006811115611b8c57611b8b6135f2565b5b81526020019081526020016000205490508260076000846006811115611bb557611bb46135f2565b5b6006811115611bc757611bc66135f2565b5b8152602001908152602001600020819055507ff058ebb04b0c3ea9966ded51962235511f002d359beb2f23415c92b6f49f7385828285604051611c0c93929190614101565b60405180910390a15050508080611c2290613fe3565b915050611ace565b50505050565b60028181548110611c4057600080fd5b906000526020600020016000915090505481565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6001611c8581612921565b611d11858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050612a12565b848460019190611d22929190612de4565b50828260029190611d34929190612de4565b507f21336086afa28f44951f6287ed7224dfa13b3403e2897cbad149b2f9742593cd85856002604051611d699392919061420e565b60405180910390a15050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754905090565b60086020528060005260406000206000915054906101000a900460ff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60606000600667ffffffffffffffff811115611e0457611e03613626565b5b604051908082528060200260200182016040528015611e325781602001602082028036833780820191505090505b50905060005b8151811015611ec95760076000600183611e529190613d4a565b6006811115611e6457611e636135f2565b5b6006811115611e7657611e756135f2565b5b6006811115611e8857611e876135f2565b5b815260200190815260200160002054828281518110611eaa57611ea9613b56565b5b6020026020010181815250508080611ec190613fe3565b915050611e38565b508091505090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6001611f0281612921565b611f0a6118fb565b611f1b57611f16612c57565b611f24565b611f23612cb9565b5b50565b611f2f612785565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e856040518263ffffffff1660e01b8152600401611f8a91906130d8565b602060405180830381865afa158015611fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcb9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461202f576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115612069576040517f70f65caa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061209e33868460405160200161208393929190614293565b604051602081830303815290604052805190602001206127c6565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661213085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050836127f890919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff161461217d576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f876040518263ffffffff1660e01b81526004016121da91906130d8565b600060405180830381865afa1580156121f7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122209190613f6e565b905060016002811115612236576122356135f2565b5b8160600151600281111561224d5761224c6135f2565b5b14612284576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600167ffffffffffffffff8111156122a1576122a0613626565b5b6040519080825280602002602001820160405280156122cf5781602001602082028036833780820191505090505b50905086816000815181106122e7576122e6613b56565b5b602002602001018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cf46fd01826040518263ffffffff1660e01b815260040161234e9190613479565b600060405180830381600087803b15801561236857600080fd5b505af115801561237c573d6000803e3d6000fd5b505050506000600167ffffffffffffffff81111561239d5761239c613626565b5b6040519080825280602002602001820160405280156123cb5781602001602082028036833780820191505090505b5090508260000151816000815181106123e7576123e6613b56565b5b6020026020010181815250506123fb612dc2565b61271081600186608001516006811115612418576124176135f2565b5b61242291906142db565b6006811061243357612432613b56565b5b602002018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca38383336040518463ffffffff1660e01b815260040161249b93929190613c09565b600060405180830381600087803b1580156124b557600080fd5b505af11580156124c9573d6000803e3d6000fd5b5050505087876040516124dd92919061434e565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167fc9b7aa7d93e3038e3e375eb5b0f7e9b971f172a47475000bc5625c60632ed3218b60405161252b91906130d8565b60405180910390a3505050505050505050565b61254661273d565b63389a75e1600c52806000526020600c20805442111561256e57636f5e88186000526004601cfd5b600081555061257c8161294a565b50565b61258761273d565b8060601b61259d57637448fbae6000526004601cfd5b6125a68161294a565b50565b60016125b481612921565b600060068111156125c8576125c76135f2565b5b8360068111156125db576125da6135f2565b5b03612612576040517feb6f0afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000821480612622575061271082115b15612659576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060076000856006811115612672576126716135f2565b5b6006811115612684576126836135f2565b5b815260200190815260200160002054905082600760008660068111156126ad576126ac6135f2565b5b60068111156126bf576126be6135f2565b5b8152602001908152602001600020819055507ff058ebb04b0c3ea9966ded51962235511f002d359beb2f23415c92b6f49f738584828560405161270493929190614101565b60405180910390a150505050565b600063389a75e1600c52816000526020600c20549050919050565b61273982826000612d1b565b5050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314612773576382b429006000526004601cfd5b565b61278182826001612d1b565b5050565b61278d6118fb565b156127c4576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000816020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c6004209050919050565b60006001905060405160011561286257836000526020830151604052604083510361283c576040830151601b8160ff1c016020528060011b60011c60605250612862565b604183510361285d57606083015160001a6020526040830151606052612862565b600091505b6020600160806000855afa5191503d61288357638baa579f6000526004601cfd5b6000606052806040525092915050565b60006202a300905090565b6128a6612dc2565b60006006808111156128bb576128ba6135f2565b5b8360068111156128ce576128cd6135f2565b5b146128f75760018360068111156128e8576128e76135f2565b5b6128f291906142db565b6128fa565b60055b905061271082826006811061291257612911613b56565b5b60200201818152505050919050565b638b78c6d8600c5233600052806020600c205416612947576382b429006000526004601cfd5b50565b612952612d75565b156129b8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3811560ff1b8217815550612a0f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3818155505b50565b8051825114612a4d576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000825103612a88576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1b91906135c5565b905060008060005b8551811015612c14576000868281518110612b4157612b40613b56565b5b602002602001015190506000811480612b5957508481115b15612b90576040517fadb070da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001808285901c1603612bcf576040517f2ba6e3e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001901b83179250858281518110612beb57612bea613b56565b5b602002602001015184612bfe9190613d4a565b9350508080612c0c90613fe3565b915050612b23565b506127108214612c50576040517f940addc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b612c5f612785565b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612ca2612d7a565b604051612caf9190613081565b60405180910390a1565b612cc1612d82565b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612d04612d7a565b604051612d119190613081565b60405180910390a1565b638b78c6d8600c52826000526020600c20805483811783612d3e57848216821890505b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b600090565b600033905090565b612d8a6118fb565b612dc0576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6040518060c00160405280600690602082028036833780820191505090505090565b828054828255906000526020600020908101928215612e20579160200282015b82811115612e1f578235825591602001919060010190612e04565b5b509050612e2d9190612e31565b5090565b5b80821115612e4a576000816000905550600101612e32565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b612e7581612e62565b8114612e8057600080fd5b50565b600081359050612e9281612e6c565b92915050565b600060208284031215612eae57612ead612e58565b5b6000612ebc84828501612e83565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612ef082612ec5565b9050919050565b612f0081612ee5565b8114612f0b57600080fd5b50565b600081359050612f1d81612ef7565b92915050565b60008060408385031215612f3a57612f39612e58565b5b6000612f4885828601612f0e565b9250506020612f5985828601612e83565b9150509250929050565b60008115159050919050565b612f7881612f63565b82525050565b6000602082019050612f936000830184612f6f565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612fbe57612fbd612f99565b5b8235905067ffffffffffffffff811115612fdb57612fda612f9e565b5b602083019150836001820283011115612ff757612ff6612fa3565b5b9250929050565b6000806000806060858703121561301857613017612e58565b5b600061302687828801612e83565b945050602061303787828801612e83565b935050604085013567ffffffffffffffff81111561305857613057612e5d565b5b61306487828801612fa8565b925092505092959194509250565b61307b81612ee5565b82525050565b60006020820190506130966000830184613072565b92915050565b6000602082840312156130b2576130b1612e58565b5b60006130c084828501612f0e565b91505092915050565b6130d281612e62565b82525050565b60006020820190506130ed60008301846130c9565b92915050565b60008083601f84011261310957613108612f99565b5b8235905067ffffffffffffffff81111561312657613125612f9e565b5b60208301915083602082028301111561314257613141612fa3565b5b9250929050565b600080602083850312156131605761315f612e58565b5b600083013567ffffffffffffffff81111561317e5761317d612e5d565b5b61318a858286016130f3565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156131d05780820151818401526020810190506131b5565b60008484015250505050565b6000601f19601f8301169050919050565b60006131f882613196565b61320281856131a1565b93506132128185602086016131b2565b61321b816131dc565b840191505092915050565b6000602082019050818103600083015261324081846131ed565b905092915050565b6000819050919050565b600061326d61326861326384612ec5565b613248565b612ec5565b9050919050565b600061327f82613252565b9050919050565b600061329182613274565b9050919050565b6132a181613286565b82525050565b60006020820190506132bc6000830184613298565b92915050565b60006132cd82613274565b9050919050565b6132dd816132c2565b82525050565b60006020820190506132f860008301846132d4565b92915050565b6000806000806040858703121561331857613317612e58565b5b600085013567ffffffffffffffff81111561333657613335612e5d565b5b613342878288016130f3565b9450945050602085013567ffffffffffffffff81111561336557613364612e5d565b5b613371878288016130f3565b925092505092959194509250565b600061338a82613274565b9050919050565b61339a8161337f565b82525050565b60006020820190506133b56000830184613391565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133f081612e62565b82525050565b600061340283836133e7565b60208301905092915050565b6000602082019050919050565b6000613426826133bb565b61343081856133c6565b935061343b836133d7565b8060005b8381101561346c57815161345388826133f6565b975061345e8361340e565b92505060018101905061343f565b5085935050505092915050565b60006020820190508181036000830152613493818461341b565b905092915050565b60006134a682613274565b9050919050565b6134b68161349b565b82525050565b60006020820190506134d160008301846134ad565b92915050565b600080600080606085870312156134f1576134f0612e58565b5b60006134ff87828801612e83565b945050602085013567ffffffffffffffff8111156135205761351f612e5d565b5b61352c87828801612fa8565b9350935050604061353f87828801612e83565b91505092959194509250565b6007811061355857600080fd5b50565b60008135905061356a8161354b565b92915050565b6000806040838503121561358757613586612e58565b5b60006135958582860161355b565b92505060206135a685828601612e83565b9150509250929050565b6000815190506135bf81612e6c565b92915050565b6000602082840312156135db576135da612e58565b5b60006135e9848285016135b0565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61365e826131dc565b810181811067ffffffffffffffff8211171561367d5761367c613626565b5b80604052505050565b6000613690612e4e565b905061369c8282613655565b919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156136c6576136c5613626565b5b6136cf826131dc565b9050602081019050919050565b60006136ef6136ea846136ab565b613686565b90508281526020810184848401111561370b5761370a6136a6565b5b6137168482856131b2565b509392505050565b600082601f83011261373357613732612f99565b5b81516137438482602086016136dc565b91505092915050565b6003811061375957600080fd5b50565b60008151905061376b8161374c565b92915050565b6000815190506137808161354b565b92915050565b600061ffff82169050919050565b61379d81613786565b81146137a857600080fd5b50565b6000815190506137ba81613794565b92915050565b6000608082840312156137d6576137d5613621565b5b6137e06080613686565b905060006137f0848285016135b0565b6000830152506020613804848285016135b0565b6020830152506040613818848285016135b0565b604083015250606061382c848285016135b0565b60608301525092915050565b600067ffffffffffffffff82111561385357613852613626565b5b602082029050602081019050919050565b600061387761387284613838565b613686565b9050808382526020820190506020840283018581111561389a57613899612fa3565b5b835b818110156138c357806138af88826137ab565b84526020840193505060208101905061389c565b5050509392505050565b600082601f8301126138e2576138e1612f99565b5b81516138f2848260208601613864565b91505092915050565b6000610140828403121561391257613911613621565b5b61391c60e0613686565b9050600082015167ffffffffffffffff81111561393c5761393b6136a1565b5b6139488482850161371e565b600083015250602082015167ffffffffffffffff81111561396c5761396b6136a1565b5b6139788482850161371e565b602083015250604061398c8482850161375c565b60408301525060606139a084828501613771565b60608301525060806139b4848285016137ab565b60808301525060a06139c8848285016137c0565b60a08301525061012082015167ffffffffffffffff8111156139ed576139ec6136a1565b5b6139f9848285016138cd565b60c08301525092915050565b600060208284031215613a1b57613a1a612e58565b5b600082015167ffffffffffffffff811115613a3957613a38612e5d565b5b613a45848285016138fb565b91505092915050565b60008160601b9050919050565b6000613a6682613a4e565b9050919050565b6000613a7882613a5b565b9050919050565b613a90613a8b82612ee5565b613a6d565b82525050565b6000819050919050565b613ab1613aac82612e62565b613a96565b82525050565b600081905092915050565b7f4641000000000000000000000000000000000000000000000000000000000000600082015250565b6000613af8600283613ab7565b9150613b0382613ac2565b600282019050919050565b6000613b1a8286613a7f565b601482019150613b2a8285613aa0565b602082019150613b3a8284613aa0565b602082019150613b4982613aeb565b9150819050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060069050919050565b600081905092915050565b6000819050919050565b6000602082019050919050565b613bbb81613b85565b613bc58184613b90565b9250613bd082613b9b565b8060005b83811015613c01578151613be887826133f6565b9650613bf383613ba5565b925050600181019050613bd4565b505050505050565b6000610100820190508181036000830152613c24818661341b565b9050613c336020830185613bb2565b613c4060e0830184613072565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613c8282612e62565b9150613c8d83612e62565b925082613c9d57613c9c613c48565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613ce282612e62565b9150613ced83612e62565b925082613cfd57613cfc613c48565b5b828204905092915050565b6000613d1382612e62565b9150613d1e83612e62565b9250828202613d2c81612e62565b91508282048414831517613d4357613d42613ca8565b5b5092915050565b6000613d5582612e62565b9150613d6083612e62565b9250828201905080821115613d7857613d77613ca8565b5b92915050565b600081519050613d8d81612ef7565b92915050565b600060208284031215613da957613da8612e58565b5b6000613db784828501613d7e565b91505092915050565b600067ffffffffffffffff821115613ddb57613dda613626565b5b602082029050919050565b6000613df9613df484613dc0565b613686565b90508060208402830185811115613e1357613e12612fa3565b5b835b81811015613e3c5780613e2888826135b0565b845260208401935050602081019050613e15565b5050509392505050565b600082601f830112613e5b57613e5a612f99565b5b6003613e68848285613de6565b91505092915050565b60006101c08284031215613e8857613e87613621565b5b613e93610120613686565b90506000613ea3848285016135b0565b6000830152506020613eb7848285016135b0565b6020830152506040613ecb848285016135b0565b6040830152506060613edf8482850161375c565b6060830152506080613ef384828501613771565b60808301525060a0613f07848285016137ab565b60a08301525060c0613f1b848285016137c0565b60c08301525061014082015167ffffffffffffffff811115613f4057613f3f6136a1565b5b613f4c848285016138cd565b60e083015250610160613f6184828501613e46565b6101008301525092915050565b600060208284031215613f8457613f83612e58565b5b600082015167ffffffffffffffff811115613fa257613fa1612e5d565b5b613fae84828501613e71565b91505092915050565b6000613fc38285613aa0565b602082019150613fd38284613aa0565b6020820191508190509392505050565b6000613fee82612e62565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140205761401f613ca8565b5b600182019050919050565b600080fd5b82818337505050565b600061404583856133c6565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156140785761407761402b565b5b602083029250614089838584614030565b82840190509392505050565b600060208201905081810360008301526140b0818486614039565b90509392505050565b600781106140ca576140c96135f2565b5b50565b60008190506140db826140b9565b919050565b60006140eb826140cd565b9050919050565b6140fb816140e0565b82525050565b600060608201905061411660008301866140f2565b61412360208301856130c9565b61413060408301846130c9565b949350505050565b600081549050919050565b60008190508160005260206000209050919050565b60008160001c9050919050565b6000819050919050565b600061418261417d83614158565b614165565b9050919050565b6000614195825461416f565b9050919050565b6000600182019050919050565b60006141b482614138565b6141be81856133c6565b93506141c983614143565b8060005b83811015614201576141de82614189565b6141e888826133f6565b97506141f38361419c565b9250506001810190506141cd565b5085935050505092915050565b60006040820190508181036000830152614229818587614039565b9050818103602083015261423d81846141a9565b9050949350505050565b7f5246000000000000000000000000000000000000000000000000000000000000600082015250565b600061427d600283613ab7565b915061428882614247565b600282019050919050565b600061429f8286613a7f565b6014820191506142af8285613aa0565b6020820191506142bf8284613aa0565b6020820191506142ce82614270565b9150819050949350505050565b60006142e682612e62565b91506142f183612e62565b925082820390508181111561430957614308613ca8565b5b92915050565b600081905092915050565b82818337600083830152505050565b6000614335838561430f565b935061434283858461431a565b82840190509392505050565b600061435b828486614329565b9150819050939250505056fea2646970667358221220775d7d8a97fbf134477b26bff9f1fa4d72c0b775fb41d99a20cd7c2e9dce1f9264736f6c6343000814003300000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de50000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd70000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Deployed Bytecode
0x6080604052600436106101e35760003560e01c8063715018a611610102578063aaec03f911610095578063f04e283e11610064578063f04e283e14610658578063f2fde38b14610674578063f7a2e7a614610690578063fee81cf4146106b9576101e3565b8063aaec03f9146105c2578063bad956a0146105ed578063c4ae316814610618578063d7be9db31461062f576101e3565b80637e941a0d116100d15780637e941a0d146105065780638da5cb5b1461052f57806394d0d3a61461055a57806397d7577614610597576101e3565b8063715018a61461046b57806372dcb18a14610475578063788986741461049e5780637afb9b1d146104db576101e3565b80633d5381101161017a57806354fd4d501161014957806354fd4d50146103c15780635c975abb146103ec578063684931ed146104175780636c19e78314610442576101e3565b80633d538110146103355780634a4ee7b11461035e578063514e62fc1461037a57806354d1f13d146103b7576101e3565b8063238ac933116101b6578063238ac9331461028657806325692962146102b15780632de94807146102bb57806338c73fd4146102f8576101e3565b8063183a4f6e146101e85780631c10893f146102045780631cd64df41461022057806320b4eb021461025d575b600080fd5b61020260048036038101906101fd9190612e98565b6106f6565b005b61021e60048036038101906102199190612f23565b610703565b005b34801561022c57600080fd5b5061024760048036038101906102429190612f23565b610719565b6040516102549190612f7e565b60405180910390f35b34801561026957600080fd5b50610284600480360381019061027f9190612ffe565b610730565b005b34801561029257600080fd5b5061029b610bb7565b6040516102a89190613081565b60405180910390f35b6102b9610bdd565b005b3480156102c757600080fd5b506102e260048036038101906102dd919061309c565b610c31565b6040516102ef91906130d8565b60405180910390f35b34801561030457600080fd5b5061031f600480360381019061031a9190612e98565b610c4c565b60405161032c91906130d8565b60405180910390f35b34801561034157600080fd5b5061035c60048036038101906103579190613149565b610c70565b005b61037860048036038101906103739190612f23565b611854565b005b34801561038657600080fd5b506103a1600480360381019061039c9190612f23565b61186a565b6040516103ae9190612f7e565b60405180910390f35b6103bf611882565b005b3480156103cd57600080fd5b506103d66118be565b6040516103e39190613226565b60405180910390f35b3480156103f857600080fd5b506104016118fb565b60405161040e9190612f7e565b60405180910390f35b34801561042357600080fd5b5061042c611911565b60405161043991906132a7565b60405180910390f35b34801561044e57600080fd5b506104696004803603810190610464919061309c565b611937565b005b610473611a6f565b005b34801561048157600080fd5b5061049c60048036038101906104979190613149565b611a83565b005b3480156104aa57600080fd5b506104c560048036038101906104c09190612e98565b611c30565b6040516104d291906130d8565b60405180910390f35b3480156104e757600080fd5b506104f0611c54565b6040516104fd91906132e3565b60405180910390f35b34801561051257600080fd5b5061052d600480360381019061052891906132fe565b611c7a565b005b34801561053b57600080fd5b50610544611d78565b6040516105519190613081565b60405180910390f35b34801561056657600080fd5b50610581600480360381019061057c9190612e98565b611da1565b60405161058e9190612f7e565b60405180910390f35b3480156105a357600080fd5b506105ac611dc1565b6040516105b991906133a0565b60405180910390f35b3480156105ce57600080fd5b506105d7611de5565b6040516105e49190613479565b60405180910390f35b3480156105f957600080fd5b50610602611ed1565b60405161060f91906134bc565b60405180910390f35b34801561062457600080fd5b5061062d611ef7565b005b34801561063b57600080fd5b50610656600480360381019061065191906134d7565b611f27565b005b610672600480360381019061066d919061309c565b61253e565b005b61068e6004803603810190610689919061309c565b61257f565b005b34801561069c57600080fd5b506106b760048036038101906106b29190613570565b6125a9565b005b3480156106c557600080fd5b506106e060048036038101906106db919061309c565b612712565b6040516106ed91906130d8565b60405180910390f35b610700338261272d565b50565b61070b61273d565b6107158282612775565b5050565b6000818261072685610c31565b1614905092915050565b610738612785565b60008414806107d65750600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d391906135c5565b84115b1561080d576040517f0d4a929c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002808111156108205761081f6135f2565b5b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663abb05174866040518263ffffffff1660e01b815260040161087b91906130d8565b600060405180830381865afa158015610898573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906108c19190613a05565b6040015160028111156108d7576108d66135f2565b5b1461090e576040517fdbbad12800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061094333868660405160200161092893929190613b0e565b604051602081830303815290604052805190602001206127c6565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166109d584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050836127f890919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff1614610a22576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6008600085815260200190815260200160002060009054906101000a900460ff1615610a7a576040517f1f6d5aef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600086815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600167ffffffffffffffff811115610ac357610ac2613626565b5b604051908082528060200260200182016040528015610af15781602001602082028036833780820191505090505b5090508581600081518110610b0957610b08613b56565b5b602002602001018181525050610b1d612dc2565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca38383336040518463ffffffff1660e01b8152600401610b7c93929190613c09565b600060405180830381600087803b158015610b9657600080fd5b505af1158015610baa573d6000803e3d6000fd5b5050505050505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610be7612893565b67ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b6000638b78c6d8600c52816000526020600c20549050919050565b60018181548110610c5c57600080fd5b906000526020600020016000915090505481565b610c78612785565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cdd576040517fe02c6ccf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008282905003610d1a576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600283839050610d2c9190613c77565b14610d63576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663055877756040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df891906135c5565b90506000600284849050610e0c9190613cd7565b90506014811115610e49576040517f1afb23e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115610e6557610e64613626565b5b604051908082528060200260200182016040528015610e935781602001602082028036833780820191505090505b50905060008267ffffffffffffffff811115610eb257610eb1613626565b5b604051908082528060200260200182016040528015610ee05781602001602082028036833780820191505090505b50905060005b8381101561165f5760008787600284610eff9190613d08565b818110610f0f57610f0e613b56565b5b905060200201359050600088886001600286610f2b9190613d08565b610f359190613d4a565b818110610f4557610f44613b56565b5b905060200201359050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610fa991906130d8565b602060405180830381865afa158015610fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fea9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461104e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e826040518263ffffffff1660e01b81526004016110a991906130d8565b602060405180830381865afa1580156110c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ea9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461114e576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f846040518263ffffffff1660e01b81526004016111ab91906130d8565b600060405180830381865afa1580156111c8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906111f19190613f6e565b90506000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f846040518263ffffffff1660e01b815260040161125091906130d8565b600060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906112969190613f6e565b9050806080015160068111156112af576112ae6135f2565b5b826080015160068111156112c6576112c56135f2565b5b146112fd576040517f41dc2d2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016002811115611311576113106135f2565b5b82606001516002811115611328576113276135f2565b5b14158061135e575060016002811115611344576113436135f2565b5b8160600151600281111561135b5761135a6135f2565b5b14155b15611395576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060076000846080015160068111156113b2576113b16135f2565b5b60068111156113c4576113c36135f2565b5b81526020019081526020016000205490506000810361140f576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060016127108c89604051602001611429929190613fb7565b6040516020818303038152906040528051906020012060001c61144c9190613c77565b6114569190613d4a565b905060006001612710838a604051602001611472929190613fb7565b6040516020818303038152906040528051906020012060001c6114959190613c77565b61149f9190613d4a565b905082821161155e576006808111156114bb576114ba6135f2565b5b856080015160068111156114d2576114d16135f2565b5b14611511576001856080015160068111156114f0576114ef6135f2565b5b6114fa9190613d4a565b600681111561150c5761150b6135f2565b5b611514565b60065b89898151811061152757611526613b56565b5b60200260200101906006811115611541576115406135f2565b5b90816006811115611555576115546135f2565b5b815250506115a9565b846080015189898151811061157657611575613b56565b5b602002602001019060068111156115905761158f6135f2565b5b908160068111156115a4576115a36135f2565b5b815250505b6000805b60028054905081101561164357600281815481106115ce576115cd613b56565b5b9060005260206000200154826115e49190613d4a565b9150818311611630576001818154811061160157611600613b56565b5b90600052602060002001548c8b8151811061161f5761161e613b56565b5b602002602001018181525050611643565b808061163b90613fe3565b9150506115ad565b505050505050505050808061165790613fe3565b915050610ee6565b50600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cf46fd0187876040518363ffffffff1660e01b81526004016116bd929190614095565b600060405180830381600087803b1580156116d757600080fd5b505af11580156116eb573d6000803e3d6000fd5b5050505060005b825181101561184b576000600167ffffffffffffffff81111561171857611717613626565b5b6040519080825280602002602001820160405280156117465781602001602082028036833780820191505090505b50905083828151811061175c5761175b613b56565b5b60200260200101518160008151811061177857611777613b56565b5b602002602001018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca3826117e68686815181106117d9576117d8613b56565b5b602002602001015161289e565b336040518463ffffffff1660e01b815260040161180593929190613c09565b600060405180830381600087803b15801561181f57600080fd5b505af1158015611833573d6000803e3d6000fd5b5050505050808061184390613fe3565b9150506116f2565b50505050505050565b61185c61273d565b611866828261272d565b5050565b6000808261187785610c31565b161415905092915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b60606040518060400160405280600581526020017f322e302e30000000000000000000000000000000000000000000000000000000815250905090565b60008060009054906101000a900460ff16905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600161194281612921565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119a8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb60405160405180910390a3505050565b611a7761273d565b611a81600061294a565b565b6001611a8e81612921565b60068383905014611acb576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b83839050811015611c2a576000848483818110611aee57611aed613b56565b5b9050602002013590506000811480611b07575061271081115b15611b3e576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600183611b4d9190613d4a565b6006811115611b5f57611b5e6135f2565b5b9050600060076000836006811115611b7a57611b796135f2565b5b6006811115611b8c57611b8b6135f2565b5b81526020019081526020016000205490508260076000846006811115611bb557611bb46135f2565b5b6006811115611bc757611bc66135f2565b5b8152602001908152602001600020819055507ff058ebb04b0c3ea9966ded51962235511f002d359beb2f23415c92b6f49f7385828285604051611c0c93929190614101565b60405180910390a15050508080611c2290613fe3565b915050611ace565b50505050565b60028181548110611c4057600080fd5b906000526020600020016000915090505481565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6001611c8581612921565b611d11858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050848480806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050612a12565b848460019190611d22929190612de4565b50828260029190611d34929190612de4565b507f21336086afa28f44951f6287ed7224dfa13b3403e2897cbad149b2f9742593cd85856002604051611d699392919061420e565b60405180910390a15050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754905090565b60086020528060005260406000206000915054906101000a900460ff1681565b7f000000000000000000000000430000000000000000000000000000000000000281565b60606000600667ffffffffffffffff811115611e0457611e03613626565b5b604051908082528060200260200182016040528015611e325781602001602082028036833780820191505090505b50905060005b8151811015611ec95760076000600183611e529190613d4a565b6006811115611e6457611e636135f2565b5b6006811115611e7657611e756135f2565b5b6006811115611e8857611e876135f2565b5b815260200190815260200160002054828281518110611eaa57611ea9613b56565b5b6020026020010181815250508080611ec190613fe3565b915050611e38565b508091505090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6001611f0281612921565b611f0a6118fb565b611f1b57611f16612c57565b611f24565b611f23612cb9565b5b50565b611f2f612785565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e856040518263ffffffff1660e01b8152600401611f8a91906130d8565b602060405180830381865afa158015611fa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcb9190613d93565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461202f576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115612069576040517f70f65caa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061209e33868460405160200161208393929190614293565b604051602081830303815290604052805190602001206127c6565b9050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661213085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050836127f890919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff161461217d576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634dc0884f876040518263ffffffff1660e01b81526004016121da91906130d8565b600060405180830381865afa1580156121f7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906122209190613f6e565b905060016002811115612236576122356135f2565b5b8160600151600281111561224d5761224c6135f2565b5b14612284576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600167ffffffffffffffff8111156122a1576122a0613626565b5b6040519080825280602002602001820160405280156122cf5781602001602082028036833780820191505090505b50905086816000815181106122e7576122e6613b56565b5b602002602001018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cf46fd01826040518263ffffffff1660e01b815260040161234e9190613479565b600060405180830381600087803b15801561236857600080fd5b505af115801561237c573d6000803e3d6000fd5b505050506000600167ffffffffffffffff81111561239d5761239c613626565b5b6040519080825280602002602001820160405280156123cb5781602001602082028036833780820191505090505b5090508260000151816000815181106123e7576123e6613b56565b5b6020026020010181815250506123fb612dc2565b61271081600186608001516006811115612418576124176135f2565b5b61242291906142db565b6006811061243357612432613b56565b5b602002018181525050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166303728ca38383336040518463ffffffff1660e01b815260040161249b93929190613c09565b600060405180830381600087803b1580156124b557600080fd5b505af11580156124c9573d6000803e3d6000fd5b5050505087876040516124dd92919061434e565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167fc9b7aa7d93e3038e3e375eb5b0f7e9b971f172a47475000bc5625c60632ed3218b60405161252b91906130d8565b60405180910390a3505050505050505050565b61254661273d565b63389a75e1600c52806000526020600c20805442111561256e57636f5e88186000526004601cfd5b600081555061257c8161294a565b50565b61258761273d565b8060601b61259d57637448fbae6000526004601cfd5b6125a68161294a565b50565b60016125b481612921565b600060068111156125c8576125c76135f2565b5b8360068111156125db576125da6135f2565b5b03612612576040517feb6f0afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000821480612622575061271082115b15612659576040517f1849438700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060076000856006811115612672576126716135f2565b5b6006811115612684576126836135f2565b5b815260200190815260200160002054905082600760008660068111156126ad576126ac6135f2565b5b60068111156126bf576126be6135f2565b5b8152602001908152602001600020819055507ff058ebb04b0c3ea9966ded51962235511f002d359beb2f23415c92b6f49f738584828560405161270493929190614101565b60405180910390a150505050565b600063389a75e1600c52816000526020600c20549050919050565b61273982826000612d1b565b5050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314612773576382b429006000526004601cfd5b565b61278182826001612d1b565b5050565b61278d6118fb565b156127c4576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000816020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c6004209050919050565b60006001905060405160011561286257836000526020830151604052604083510361283c576040830151601b8160ff1c016020528060011b60011c60605250612862565b604183510361285d57606083015160001a6020526040830151606052612862565b600091505b6020600160806000855afa5191503d61288357638baa579f6000526004601cfd5b6000606052806040525092915050565b60006202a300905090565b6128a6612dc2565b60006006808111156128bb576128ba6135f2565b5b8360068111156128ce576128cd6135f2565b5b146128f75760018360068111156128e8576128e76135f2565b5b6128f291906142db565b6128fa565b60055b905061271082826006811061291257612911613b56565b5b60200201818152505050919050565b638b78c6d8600c5233600052806020600c205416612947576382b429006000526004601cfd5b50565b612952612d75565b156129b8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3811560ff1b8217815550612a0f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3818155505b50565b8051825114612a4d576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000825103612a88576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b1b91906135c5565b905060008060005b8551811015612c14576000868281518110612b4157612b40613b56565b5b602002602001015190506000811480612b5957508481115b15612b90576040517fadb070da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001808285901c1603612bcf576040517f2ba6e3e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001901b83179250858281518110612beb57612bea613b56565b5b602002602001015184612bfe9190613d4a565b9350508080612c0c90613fe3565b915050612b23565b506127108214612c50576040517f940addc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b612c5f612785565b60016000806101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612ca2612d7a565b604051612caf9190613081565b60405180910390a1565b612cc1612d82565b60008060006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612d04612d7a565b604051612d119190613081565b60405180910390a1565b638b78c6d8600c52826000526020600c20805483811783612d3e57848216821890505b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b600090565b600033905090565b612d8a6118fb565b612dc0576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6040518060c00160405280600690602082028036833780820191505090505090565b828054828255906000526020600020908101928215612e20579160200282015b82811115612e1f578235825591602001919060010190612e04565b5b509050612e2d9190612e31565b5090565b5b80821115612e4a576000816000905550600101612e32565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b612e7581612e62565b8114612e8057600080fd5b50565b600081359050612e9281612e6c565b92915050565b600060208284031215612eae57612ead612e58565b5b6000612ebc84828501612e83565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612ef082612ec5565b9050919050565b612f0081612ee5565b8114612f0b57600080fd5b50565b600081359050612f1d81612ef7565b92915050565b60008060408385031215612f3a57612f39612e58565b5b6000612f4885828601612f0e565b9250506020612f5985828601612e83565b9150509250929050565b60008115159050919050565b612f7881612f63565b82525050565b6000602082019050612f936000830184612f6f565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612fbe57612fbd612f99565b5b8235905067ffffffffffffffff811115612fdb57612fda612f9e565b5b602083019150836001820283011115612ff757612ff6612fa3565b5b9250929050565b6000806000806060858703121561301857613017612e58565b5b600061302687828801612e83565b945050602061303787828801612e83565b935050604085013567ffffffffffffffff81111561305857613057612e5d565b5b61306487828801612fa8565b925092505092959194509250565b61307b81612ee5565b82525050565b60006020820190506130966000830184613072565b92915050565b6000602082840312156130b2576130b1612e58565b5b60006130c084828501612f0e565b91505092915050565b6130d281612e62565b82525050565b60006020820190506130ed60008301846130c9565b92915050565b60008083601f84011261310957613108612f99565b5b8235905067ffffffffffffffff81111561312657613125612f9e565b5b60208301915083602082028301111561314257613141612fa3565b5b9250929050565b600080602083850312156131605761315f612e58565b5b600083013567ffffffffffffffff81111561317e5761317d612e5d565b5b61318a858286016130f3565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156131d05780820151818401526020810190506131b5565b60008484015250505050565b6000601f19601f8301169050919050565b60006131f882613196565b61320281856131a1565b93506132128185602086016131b2565b61321b816131dc565b840191505092915050565b6000602082019050818103600083015261324081846131ed565b905092915050565b6000819050919050565b600061326d61326861326384612ec5565b613248565b612ec5565b9050919050565b600061327f82613252565b9050919050565b600061329182613274565b9050919050565b6132a181613286565b82525050565b60006020820190506132bc6000830184613298565b92915050565b60006132cd82613274565b9050919050565b6132dd816132c2565b82525050565b60006020820190506132f860008301846132d4565b92915050565b6000806000806040858703121561331857613317612e58565b5b600085013567ffffffffffffffff81111561333657613335612e5d565b5b613342878288016130f3565b9450945050602085013567ffffffffffffffff81111561336557613364612e5d565b5b613371878288016130f3565b925092505092959194509250565b600061338a82613274565b9050919050565b61339a8161337f565b82525050565b60006020820190506133b56000830184613391565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133f081612e62565b82525050565b600061340283836133e7565b60208301905092915050565b6000602082019050919050565b6000613426826133bb565b61343081856133c6565b935061343b836133d7565b8060005b8381101561346c57815161345388826133f6565b975061345e8361340e565b92505060018101905061343f565b5085935050505092915050565b60006020820190508181036000830152613493818461341b565b905092915050565b60006134a682613274565b9050919050565b6134b68161349b565b82525050565b60006020820190506134d160008301846134ad565b92915050565b600080600080606085870312156134f1576134f0612e58565b5b60006134ff87828801612e83565b945050602085013567ffffffffffffffff8111156135205761351f612e5d565b5b61352c87828801612fa8565b9350935050604061353f87828801612e83565b91505092959194509250565b6007811061355857600080fd5b50565b60008135905061356a8161354b565b92915050565b6000806040838503121561358757613586612e58565b5b60006135958582860161355b565b92505060206135a685828601612e83565b9150509250929050565b6000815190506135bf81612e6c565b92915050565b6000602082840312156135db576135da612e58565b5b60006135e9848285016135b0565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61365e826131dc565b810181811067ffffffffffffffff8211171561367d5761367c613626565b5b80604052505050565b6000613690612e4e565b905061369c8282613655565b919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156136c6576136c5613626565b5b6136cf826131dc565b9050602081019050919050565b60006136ef6136ea846136ab565b613686565b90508281526020810184848401111561370b5761370a6136a6565b5b6137168482856131b2565b509392505050565b600082601f83011261373357613732612f99565b5b81516137438482602086016136dc565b91505092915050565b6003811061375957600080fd5b50565b60008151905061376b8161374c565b92915050565b6000815190506137808161354b565b92915050565b600061ffff82169050919050565b61379d81613786565b81146137a857600080fd5b50565b6000815190506137ba81613794565b92915050565b6000608082840312156137d6576137d5613621565b5b6137e06080613686565b905060006137f0848285016135b0565b6000830152506020613804848285016135b0565b6020830152506040613818848285016135b0565b604083015250606061382c848285016135b0565b60608301525092915050565b600067ffffffffffffffff82111561385357613852613626565b5b602082029050602081019050919050565b600061387761387284613838565b613686565b9050808382526020820190506020840283018581111561389a57613899612fa3565b5b835b818110156138c357806138af88826137ab565b84526020840193505060208101905061389c565b5050509392505050565b600082601f8301126138e2576138e1612f99565b5b81516138f2848260208601613864565b91505092915050565b6000610140828403121561391257613911613621565b5b61391c60e0613686565b9050600082015167ffffffffffffffff81111561393c5761393b6136a1565b5b6139488482850161371e565b600083015250602082015167ffffffffffffffff81111561396c5761396b6136a1565b5b6139788482850161371e565b602083015250604061398c8482850161375c565b60408301525060606139a084828501613771565b60608301525060806139b4848285016137ab565b60808301525060a06139c8848285016137c0565b60a08301525061012082015167ffffffffffffffff8111156139ed576139ec6136a1565b5b6139f9848285016138cd565b60c08301525092915050565b600060208284031215613a1b57613a1a612e58565b5b600082015167ffffffffffffffff811115613a3957613a38612e5d565b5b613a45848285016138fb565b91505092915050565b60008160601b9050919050565b6000613a6682613a4e565b9050919050565b6000613a7882613a5b565b9050919050565b613a90613a8b82612ee5565b613a6d565b82525050565b6000819050919050565b613ab1613aac82612e62565b613a96565b82525050565b600081905092915050565b7f4641000000000000000000000000000000000000000000000000000000000000600082015250565b6000613af8600283613ab7565b9150613b0382613ac2565b600282019050919050565b6000613b1a8286613a7f565b601482019150613b2a8285613aa0565b602082019150613b3a8284613aa0565b602082019150613b4982613aeb565b9150819050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060069050919050565b600081905092915050565b6000819050919050565b6000602082019050919050565b613bbb81613b85565b613bc58184613b90565b9250613bd082613b9b565b8060005b83811015613c01578151613be887826133f6565b9650613bf383613ba5565b925050600181019050613bd4565b505050505050565b6000610100820190508181036000830152613c24818661341b565b9050613c336020830185613bb2565b613c4060e0830184613072565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613c8282612e62565b9150613c8d83612e62565b925082613c9d57613c9c613c48565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613ce282612e62565b9150613ced83612e62565b925082613cfd57613cfc613c48565b5b828204905092915050565b6000613d1382612e62565b9150613d1e83612e62565b9250828202613d2c81612e62565b91508282048414831517613d4357613d42613ca8565b5b5092915050565b6000613d5582612e62565b9150613d6083612e62565b9250828201905080821115613d7857613d77613ca8565b5b92915050565b600081519050613d8d81612ef7565b92915050565b600060208284031215613da957613da8612e58565b5b6000613db784828501613d7e565b91505092915050565b600067ffffffffffffffff821115613ddb57613dda613626565b5b602082029050919050565b6000613df9613df484613dc0565b613686565b90508060208402830185811115613e1357613e12612fa3565b5b835b81811015613e3c5780613e2888826135b0565b845260208401935050602081019050613e15565b5050509392505050565b600082601f830112613e5b57613e5a612f99565b5b6003613e68848285613de6565b91505092915050565b60006101c08284031215613e8857613e87613621565b5b613e93610120613686565b90506000613ea3848285016135b0565b6000830152506020613eb7848285016135b0565b6020830152506040613ecb848285016135b0565b6040830152506060613edf8482850161375c565b6060830152506080613ef384828501613771565b60808301525060a0613f07848285016137ab565b60a08301525060c0613f1b848285016137c0565b60c08301525061014082015167ffffffffffffffff811115613f4057613f3f6136a1565b5b613f4c848285016138cd565b60e083015250610160613f6184828501613e46565b6101008301525092915050565b600060208284031215613f8457613f83612e58565b5b600082015167ffffffffffffffff811115613fa257613fa1612e5d565b5b613fae84828501613e71565b91505092915050565b6000613fc38285613aa0565b602082019150613fd38284613aa0565b6020820191508190509392505050565b6000613fee82612e62565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140205761401f613ca8565b5b600182019050919050565b600080fd5b82818337505050565b600061404583856133c6565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156140785761407761402b565b5b602083029250614089838584614030565b82840190509392505050565b600060208201905081810360008301526140b0818486614039565b90509392505050565b600781106140ca576140c96135f2565b5b50565b60008190506140db826140b9565b919050565b60006140eb826140cd565b9050919050565b6140fb816140e0565b82525050565b600060608201905061411660008301866140f2565b61412360208301856130c9565b61413060408301846130c9565b949350505050565b600081549050919050565b60008190508160005260206000209050919050565b60008160001c9050919050565b6000819050919050565b600061418261417d83614158565b614165565b9050919050565b6000614195825461416f565b9050919050565b6000600182019050919050565b60006141b482614138565b6141be81856133c6565b93506141c983614143565b8060005b83811015614201576141de82614189565b6141e888826133f6565b97506141f38361419c565b9250506001810190506141cd565b5085935050505092915050565b60006040820190508181036000830152614229818587614039565b9050818103602083015261423d81846141a9565b9050949350505050565b7f5246000000000000000000000000000000000000000000000000000000000000600082015250565b600061427d600283613ab7565b915061428882614247565b600282019050919050565b600061429f8286613a7f565b6014820191506142af8285613aa0565b6020820191506142bf8284613aa0565b6020820191506142ce82614270565b9150819050949350505050565b60006142e682612e62565b91506142f183612e62565b925082820390508181111561430957614308613ca8565b5b92915050565b600081905092915050565b82818337600083830152505050565b6000614335838561430f565b935061434283858461431a565b82840190509392505050565b600061435b828486614329565b9150819050939250505056fea2646970667358221220775d7d8a97fbf134477b26bff9f1fa4d72c0b775fb41d99a20cd7c2e9dce1f9264736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de50000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd70000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
-----Decoded View---------------
Arg [0] : _gameMaster (address): 0x51a16E6AEc2924e8886fc323618876e3ED0e4dE5
Arg [1] : _signer (address): 0x1facD50481D827D7d342D79278B9C5A1F9eB6CD7
Arg [2] : _seeder (address): 0x4131aE1e157c91fe083BdCf857A230fb79Ac903a
Arg [3] : _gameCards (address): 0x10FE37BAC405B209f83FF523Fb8D00C0c3F508a8
Arg [4] : _baseCards (address): 0xc8607C5BefA7A7567ca78040bA5C36d181243ac1
Arg [5] : _blastGovernor (address): 0xAbb8621b2F4FB61f083b9f2a033A40086DB9030d
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de5
Arg [1] : 0000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd7
Arg [2] : 0000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a
Arg [3] : 00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8
Arg [4] : 000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1
Arg [5] : 000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Deployed Bytecode Sourcemap
99867:12105:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63189:111;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62638:125;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;64266:141;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;105286:815;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;100287:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;19164:630;;;:::i;:::-;;63638:362;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100216:27;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;101539:3688;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62912:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;64065:136;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;19879:466;;;:::i;:::-;;109681:90;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;51880:86;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100315:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109168:272;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;18899:102;;;:::i;:::-;;108333:776;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;100250:28;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100377:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107341:360;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21604:187;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100493:54;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100125:82;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109830:361;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100343:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109499:123;;;;;;;;;;;;;:::i;:::-;;106160:1122;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;20536:724;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;18473:358;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;107760:514;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21897:449;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;63189:111;63261:31;63274:10;63286:5;63261:12;:31::i;:::-;63189:111;:::o;62638:125::-;22743:13;:11;:13::i;:::-;62731:24:::1;62743:4;62749:5;62731:11;:24::i;:::-;62638:125:::0;;:::o;64266:141::-;64345:4;64394:5;64385;64369:13;64377:4;64369:7;:13::i;:::-;:21;:30;64362:37;;64266:141;;;;:::o;105286:815::-;51485:19;:17;:19::i;:::-;105422:1:::1;105408:10;:15;:57;;;;105440:9;;;;;;;;;;;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105427:10;:38;105408:57;105404:89;;;105474:19;;;;;;;;;;;;;;105404:89;105552:22;105508:66:::0;::::1;;;;;;;:::i;:::-;;:9;;;;;;;;;;;:19;;;105528:10;105508:31;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;;:66;;;;;;;;:::i;:::-;;;105504:96;;105583:17;;;;;;;;;;;;;;105504:96;105613:14;105630:89;105657:10;105669;105681:5;105640:53;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;105630:64;;;;;;:87;:89::i;:::-;105613:106;;105763:6;;;;;;;;;;;105734:35;;:25;105749:9;;105734:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:6;:14;;:25;;;;:::i;:::-;:35;;;105730:64;;105778:16;;;;;;;;;;;;;;105730:64;105811:9;:16;105821:5;105811:16;;;;;;;;;;;;;;;;;;;;;105807:40;;;105836:11;;;;;;;;;;;;;;105807:40;105877:4;105858:9;:16;105868:5;105858:16;;;;;;;;;;;;:23;;;;;;;;;;;;;;;;;;105894:20;105931:1;105917:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105894:39;;105953:10;105944:3;105948:1;105944:6;;;;;;;;:::i;:::-;;;;;;;:19;;;::::0;::::1;105976:25;;:::i;:::-;106012:9;;;;;;;;;;;:19;;;106043:3;106061:7;106080:10;106012:81;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;105393:708;;;105286:815:::0;;;;:::o;100287:21::-;;;;;;;;;;;;;:::o;19164:630::-;19259:15;19295:28;:26;:28::i;:::-;19277:46;;:15;:46;19259:64;;19495:19;19489:4;19482:33;19546:8;19540:4;19533:22;19603:7;19596:4;19590;19580:21;19573:38;19752:8;19705:45;19702:1;19699;19694:67;19395:381;19164:630::o;63638:362::-;63698:13;63844:15;63838:4;63831:29;63887:4;63881;63874:18;63976:4;63970;63960:21;63954:28;63945:37;;63638:362;;;:::o;100216:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;101539:3688::-;51485:19;:17;:19::i;:::-;101702:9:::1;101688:23;;:10;:23;;;101684:53;;101720:17;;;;;;;;;;;;;;101684:53;101837:1;101819:7;;:14;;:19:::0;101815:49:::1;;101847:17;;;;;;;;;;;;;;101815:49;101975:1;101970;101953:7;;:14;;:18;;;;:::i;:::-;:23;101949:57;;101985:21;;;;;;;;;;;;;;101949:57;102019:21;102043:6;;;;;;;;;;;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102019:53;;102083:18;102121:1;102104:7;;:14;;:18;;;;:::i;:::-;102083:39;;100114:2;102137:10;:28;102133:59;;;102174:18;;;;;;;;;;;;;;102133:59;102205:28;102250:10;102236:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102205:56;;102272:32;102327:10;102307:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102272:66;;102509:9;102504:2190;102528:10;102524:1;:14;102504:2190;;;102560:17;102580:7;;102592:1;102588;:5;;;;:::i;:::-;102580:14;;;;;;;:::i;:::-;;;;;;;;102560:34;;102609:17;102629:7;;102645:1;102641;102637;:5;;;;:::i;:::-;:9;;;;:::i;:::-;102629:18;;;;;;;:::i;:::-;;;;;;;;102609:38;;102743:9;;;;;;;;;;;:17;;;102772:9;102743:41;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102729:55;;:10;:55;;;102725:84;;102793:16;;;;;;;;;;;;;;102725:84;102842:9;;;;;;;;;;;:17;;;102871:9;102842:41;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102828:55;;:10;:55;;;102824:84;;102892:16;;;;;;;;;;;;;;102824:84;102925:28;102956:9;;;;;;;;;;;:21;;;102989:9;102956:45;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102925:76;;103016:28;103047:9;;;;;;;;;;;:21;;;103080:9;103047:45;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103016:76;;103197:5;:14;;;103179:32;;;;;;;;:::i;:::-;;:5;:14;;;:32;;;;;;;;:::i;:::-;;;103175:63;;103220:18;;;;;;;;;;;;;;103175:63;103333:18;103315:36;;;;;;;;:::i;:::-;;:5;:14;;;:36;;;;;;;;:::i;:::-;;;;:76;;;;103373:18;103355:36;;;;;;;;:::i;:::-;;:5;:14;;;:36;;;;;;;;:::i;:::-;;;;103315:76;103311:106;;;103400:17;;;;;;;;;;;;;;103311:106;103434:21;103458:15;:31;103474:5;:14;;;103458:31;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;103434:55;;103584:1;103567:13;:18:::0;103563:53:::1;;103594:22;;;;;;;;;;;;;;103563:53;103633:19;103726:1;100058:6;103690:13;103705:1;103673:34;;;;;;;;;:::i;:::-;;;;;;;;;;;;;103663:45;;;;;;103655:54;;:68;;;;:::i;:::-;:72;;;;:::i;:::-;103633:94;;103742:21;103835:1;100006:6;103801:11;103814:1;103784:32;;;;;;;;;:::i;:::-;;;;;;;;;;;;;103774:43;;;;;;103766:52;;:66;;;;:::i;:::-;:70;;;;:::i;:::-;103742:94;;104092:13;104077:11;:28;104073:275;;104180:17;104162:35:::0;::::1;;;;;;;:::i;:::-;;:5;:14;;;:35;;;;;;;;:::i;:::-;;;:100;;104260:1;104242:5;:14;;;104234:23;;;;;;;;:::i;:::-;;:27;;;;:::i;:::-;104220:42;;;;;;;;:::i;:::-;;104162:100;;;104200:17;104162:100;104126:9;104136:1;104126:12;;;;;;;;:::i;:::-;;;;;;;:136;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;::::0;::::1;104073:275;;;104318:5;:14;;;104303:9;104313:1;104303:12;;;;;;;;:::i;:::-;;;;;;;:29;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;::::0;::::1;104073:275;104364:24;104412:9:::0;104407:276:::1;104431:11;:18;;;;104427:1;:22;104407:276;;;104495:11;104507:1;104495:14;;;;;;;;:::i;:::-;;;;;;;;;;104475:34;;;;;:::i;:::-;;;104549:16;104532:13;:33;104528:140;;104607:10;104618:1;104607:13;;;;;;;;:::i;:::-;;;;;;;;;;104590:11;104602:1;104590:14;;;;;;;;:::i;:::-;;;;;;;:30;;;::::0;::::1;104643:5;;104528:140;104451:3;;;;;:::i;:::-;;;;104407:276;;;;102545:2149;;;;;;;;102540:3;;;;;:::i;:::-;;;;102504:2190;;;;104815:9;;;;;;;;;;;:20;;;104848:7;;104815:43;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;104876:9;104871:349;104895:11;:18;104891:1;:22;104871:349;;;104935:23;104975:1;104961:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104935:42;;105004:11;105016:1;105004:14;;;;;;;;:::i;:::-;;;;;;;;104992:6;104999:1;104992:9;;;;;;;;:::i;:::-;;;;;;;:26;;;::::0;::::1;105033:9;;;;;;;;;;;:19;;;105081:6;105119:34;105140:9;105150:1;105140:12;;;;;;;;:::i;:::-;;;;;;;;105119:20;:34::i;:::-;105182:10;105033:175;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;104920:300;104915:3;;;;;:::i;:::-;;;;104871:349;;;;101610:3617;;;;101539:3688:::0;;:::o;62912:127::-;22743:13;:11;:13::i;:::-;63006:25:::1;63019:4;63025:5;63006:12;:25::i;:::-;62912:127:::0;;:::o;64065:136::-;64143:4;64192:1;64183:5;64167:13;64175:4;64167:7;:13::i;:::-;:21;:26;;64160:33;;64065:136;;;;:::o;19879:466::-;20085:19;20079:4;20072:33;20132:8;20126:4;20119:22;20185:1;20178:4;20172;20162:21;20155:32;20318:8;20272:44;20269:1;20266;20261:66;19879:466::o;109681:90::-;109723:13;109749:14;;;;;;;;;;;;;;;;;;;109681:90;:::o;51880:86::-;51927:4;51951:7;;;;;;;;;;;51944:14;;51880:86;:::o;100315:21::-;;;;;;;;;;;;;:::o;109168:272::-;41485:6;64831:18;64843:5;64831:11;:18::i;:::-;109291:1:::1;109270:23;;:9;:23;;::::0;109266:49:::1;;109302:13;;;;;;;;;;;;;;109266:49;109326:17;109346:6;;;;;;;;;;;109326:26;;109372:9;109363:6;;:18;;;;;;;;;;;;;;;;;;109422:9;109397:35;;109411:9;109397:35;;;;;;;;;;;;109255:185;109168:272:::0;;:::o;18899:102::-;22743:13;:11;:13::i;:::-;18972:21:::1;18990:1;18972:9;:21::i;:::-;18899:102::o:0;108333:776::-;41485:6;64831:18;64843:5;64831:11;:18::i;:::-;108545:1:::1;108527:7;;:14;;:19;108523:53;;108555:21;;;;;;;;;;;;;;108523:53;108592:9;108587:515;108611:7;;:14;;108607:1;:18;108587:515;;;108647:14;108664:7;;108672:1;108664:10;;;;;;;:::i;:::-;;;;;;;;108647:27;;108703:1;108693:6;:11;:35;;;;100058:6;108708;:20;108693:35;108689:70;;;108737:22;;;;;;;;;;;;;;108689:70;108849:22;108892:1;108888;:5;;;;:::i;:::-;108874:20;;;;;;;;:::i;:::-;;108849:45;;108911:24;108938:15;:25;108954:8;108938:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;108911:52;;109006:6;108978:15;:25;108994:8;108978:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:34;;;;109034:56;109055:8;109065:16;109083:6;109034:56;;;;;;;;:::i;:::-;;;;;;;;108632:470;;;108627:3;;;;;:::i;:::-;;;;108587:515;;;;108333:776:::0;;;:::o;100250:28::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;100377:27::-;;;;;;;;;;;;;:::o;107341:360::-;41485:6;64831:18;64843:5;64831:11;:18::i;:::-;107531:37:::1;107547:11;;107531:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107560:7;;107531:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:15;:37::i;:::-;107592:11;;107579:10;:24;;;;;;;:::i;:::-;;107628:7;;107614:11;:21;;;;;;;:::i;:::-;;107651:42;107668:11;;107681;107651:42;;;;;;;;:::i;:::-;;;;;;;;107341:360:::0;;;;;:::o;21604:187::-;21650:14;21761:11;21755:18;21745:28;;21604:187;:::o;100493:54::-;;;;;;;;;;;;;;;;;;;;;;:::o;100125:82::-;;;:::o;109830:361::-;109879:16;109908:24;109949:1;109935:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109908:43;;109967:9;109962:197;109986:7;:14;109982:1;:18;109962:197;;;110110:15;:37;110144:1;110140;:5;;;;:::i;:::-;110126:20;;;;;;;;:::i;:::-;;110110:37;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;110097:7;110105:1;110097:10;;;;;;;;:::i;:::-;;;;;;;:50;;;;;110002:3;;;;;:::i;:::-;;;;109962:197;;;;110176:7;110169:14;;;109830:361;:::o;100343:27::-;;;;;;;;;;;;;:::o;109499:123::-;41485:6;64831:18;64843:5;64831:11;:18::i;:::-;109582:8:::1;:6;:8::i;:::-;:32;;109606:8;:6;:8::i;:::-;109582:32;;;109593:10;:8;:10::i;:::-;109582:32;109499:123:::0;:::o;106160:1122::-;51485:19;:17;:19::i;:::-;106289:9:::1;;;;;;;;;;;:17;;;106318:6;106289:38;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106275:52;;:10;:52;;;106271:81;;106336:16;;;;;;;;;;;;;;106271:81;106385:8;106367:15;:26;106363:55;;;106402:16;;;;;;;;;;;;;;106363:55;106431:14;106448:88;106475:10;106487:6;106495:8;106458:52;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;106448:63;;;;;;:86;:88::i;:::-;106431:105;;106580:6;;;;;;;;;;;106551:35;;:25;106566:9;;106551:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:6;:14;;:25;;;;:::i;:::-;:35;;;106547:64;;106595:16;;;;;;;;;;;;;;106547:64;106624:27;106654:9;;;;;;;;;;;:21;;;106687:6;106654:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106624:72;;106728:18;106711:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;106707:65;;106755:17;;;;;;;;;;;;;;106707:65;106785:24;106826:1;106812:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106785:43;;106852:6;106839:7;106847:1;106839:10;;;;;;;;:::i;:::-;;;;;;;:19;;;::::0;::::1;106871:9;;;;;;;;;;;:20;;;106904:7;106871:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;106927:20;106964:1;106950:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106927:39;;106986:4;:15;;;106977:3;106981:1;106977:6;;;;;;;;:::i;:::-;;;;;;;:24;;;::::0;::::1;107014:25;;:::i;:::-;107088:6;107050:7;107083:1;107066:4;:13;;;107058:22;;;;;;;;:::i;:::-;;:26;;;;:::i;:::-;107050:35;;;;;;;:::i;:::-;;;;;:44;;;::::0;::::1;107107:9;;;;;;;;;;;:19;;;107138:3;107156:7;107175:10;107107:81;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;107246:9;;107206:68;;;;;;;:::i;:::-;;;;;;;;107223:10;107206:68;;;107265:6;107206:68;;;;;;:::i;:::-;;;;;;;;106260:1022;;;;;106160:1122:::0;;;;:::o;20536:724::-;22743:13;:11;:13::i;:::-;20774:19:::1;20768:4;20761:33;20821:12;20815:4;20808:26;20884:4;20878;20868:21;20992:12;20986:19;20973:11;20970:36;20967:160;;;21039:10;21033:4;21026:24;21107:4;21101;21094:18;20967:160;21206:1;21192:12;21185:23;20690:529;21229:23;21239:12;21229:9;:23::i;:::-;20536:724:::0;:::o;18473:358::-;22743:13;:11;:13::i;:::-;18648:8:::1;18644:2;18640:17;18630:153;;18691:10;18685:4;18678:24;18763:4;18757;18750:18;18630:153;18804:19;18814:8;18804:9;:19::i;:::-;18473:358:::0;:::o;107760:514::-;41485:6;64831:18;64843:5;64831:11;:18::i;:::-;107950:23:::1;107938:35;;;;;;;;:::i;:::-;;:8;:35;;;;;;;;:::i;:::-;;::::0;107934:67:::1;;107982:19;;;;;;;;;;;;;;107934:67;108026:1;108016:6;:11;:35;;;;100058:6;108031;:20;108016:35;108012:70;;;108060:22;;;;;;;;;;;;;;108012:70;108095:24;108122:15;:25;108138:8;108122:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;108095:52;;108186:6;108158:15;:25;108174:8;108158:25;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:34;;;;108210:56;108231:8;108241:16;108259:6;108210:56;;;;;;;;:::i;:::-;;;;;;;;107923:351;107760:514:::0;;;:::o;21897:449::-;22020:14;22176:19;22170:4;22163:33;22223:12;22217:4;22210:26;22322:4;22316;22306:21;22300:28;22290:38;;21897:449;;;:::o;57240:119::-;57319:32;57332:4;57338:5;57345;57319:12;:32::i;:::-;57240:119;;:::o;17394:364::-;17610:11;17604:18;17594:8;17591:32;17581:159;;17657:10;17651:4;17644:24;17720:4;17714;17707:18;17581:159;17394:364::o;56983:117::-;57061:31;57074:4;57080:5;57087:4;57061:12;:31::i;:::-;56983:117;;:::o;52039:132::-;52105:8;:6;:8::i;:::-;52101:63;;;52137:15;;;;;;;;;;;;;;52101:63;52039:132::o;38778:416::-;38847:14;38955:4;38949;38942:18;39030:50;39024:4;39017:64;39134:4;39128;39118:21;39108:31;;38778:416;;;:::o;25000:1813::-;25078:14;25183:1;25173:11;;25213:4;25207:11;25273:1;25266:706;;;25310:4;25304;25297:18;25367:4;25356:9;25352:20;25346:27;25340:4;25333:41;25424:2;25412:9;25406:16;25403:24;25400:261;;25482:4;25471:9;25467:20;25461:27;25541:2;25536;25531:3;25527:12;25523:21;25517:4;25510:35;25602:2;25599:1;25595:10;25592:1;25588:18;25582:4;25575:32;25637:5;;;25400:261;25703:2;25691:9;25685:16;25682:24;25679:226;;25772:4;25761:9;25757:20;25751:27;25748:1;25743:36;25737:4;25730:50;25844:4;25833:9;25829:20;25823:27;25817:4;25810:41;25881:5;;25679:226;25933:1;25923:11;;25266:706;26363:4;26312;26263;26213;26153:6;26078:5;26041:368;26013:415;25986:442;;26538:16;26528:147;;26588:10;26582:4;26575:24;26655:4;26649;26642:18;26528:147;26702:1;26696:4;26689:15;26757:1;26751:4;26744:15;25158:1648;25000:1813;;;;:::o;17994:112::-;18063:6;18089:9;18082:16;;17994:112;:::o;111722:247::-;111799:29;;:::i;:::-;111841:15;111871:17;111859:29;;;;;;;;:::i;:::-;;:8;:29;;;;;;;;:::i;:::-;;;:57;;111915:1;111903:8;111895:17;;;;;;;;:::i;:::-;;:21;;;;:::i;:::-;111859:57;;;111891:1;111859:57;111841:75;;100006:6;111927:11;111939:7;111927:20;;;;;;;:::i;:::-;;;;;:34;;;;;111830:139;111722:247;;;:::o;57436:567::-;57625:15;57619:4;57612:29;57668:8;57662:4;57655:22;57862:5;57854:4;57848;57838:21;57832:28;57828:40;57818:167;;57902:10;57896:4;57889:24;57965:4;57959;57952:18;57818:167;57436:567;:::o;16220:1113::-;16289:23;:21;:23::i;:::-;16285:1041;;;16422:11;16524:8;16520:2;16516:17;16512:2;16508:26;16496:38;;16680:8;16668:9;16662:16;16622:38;16619:1;16616;16611:78;16795:8;16788:16;16783:3;16779:26;16769:8;16766:40;16755:9;16748:59;16386:436;16285:1041;;;16947:11;17049:8;17045:2;17041:17;17037:2;17033:26;17021:38;;17205:8;17193:9;17187:16;17147:38;17144:1;17141;17136:78;17291:8;17280:9;17273:27;16911:404;16285:1041;16220:1113;:::o;110760:803::-;110892:7;:14;110870:11;:18;:36;110866:70;;110915:21;;;;;;;;;;;;;;110866:70;110973:1;110951:11;:18;:23;110947:53;;110983:17;;;;;;;;;;;;;;110947:53;111013:17;111033:9;;;;;;;;;;;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111013:45;;111069:17;111101:13;111136:9;111131:357;111155:11;:18;111151:1;:22;111131:357;;;111195:18;111216:11;111228:1;111216:14;;;;;;;;:::i;:::-;;;;;;;;111195:35;;111265:1;111251:10;:15;:41;;;;111283:9;111270:10;:22;111251:41;111247:73;;;111301:19;;;;;;;;;;;;;;111247:73;111366:1;111361;111348:10;111339:5;:19;;:23;:28;111335:62;;111376:21;;;;;;;;;;;;;;111335:62;111428:10;111423:1;:15;;111414:24;;;;111466:7;111474:1;111466:10;;;;;;;;:::i;:::-;;;;;;;;111453:23;;;;;:::i;:::-;;;111180:308;111175:3;;;;;:::i;:::-;;;;111131:357;;;;100006:6;111504:9;:24;111500:55;;111537:18;;;;;;;;;;;;;;111500:55;110855:708;;;110760:803;;:::o;52522:118::-;51485:19;:17;:19::i;:::-;52592:4:::1;52582:7;::::0;:14:::1;;;;;;;;;;;;;;;;;;52612:20;52619:12;:10;:12::i;:::-;52612:20;;;;;;:::i;:::-;;;;;;;;52522:118::o:0;52781:120::-;51744:16;:14;:16::i;:::-;52850:5:::1;52840:7:::0;::::1;:15;;;;;;;;;;;;;;;;;;52871:22;52880:12;:10;:12::i;:::-;52871:22;;;;;;:::i;:::-;;;;;;;;52781:120::o:0;55859:986::-;56028:15;56022:4;56015:29;56071:4;56065;56058:18;56122:4;56116;56106:21;56202:8;56196:15;56311:5;56302:7;56299:18;56559:2;56549:62;;56602:5;56593:7;56589:19;56580:7;56576:33;56565:44;;56549:62;56685:7;56675:8;56668:25;56819:7;56811:4;56805:11;56801:2;56797:20;56765:30;56762:1;56759;56754:73;56000:838;;;55859:986;;;:::o;14384:78::-;14448:10;14384:78;:::o;9760:98::-;9813:7;9840:10;9833:17;;9760:98;:::o;52248:130::-;52312:8;:6;:8::i;:::-;52307:64;;52344:15;;;;;;;;;;;;;;52307:64;52248:130::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:126::-;1062:7;1102:42;1095:5;1091:54;1080:65;;1025:126;;;:::o;1157:96::-;1194:7;1223:24;1241:5;1223:24;:::i;:::-;1212:35;;1157:96;;;:::o;1259:122::-;1332:24;1350:5;1332:24;:::i;:::-;1325:5;1322:35;1312:63;;1371:1;1368;1361:12;1312:63;1259:122;:::o;1387:139::-;1433:5;1471:6;1458:20;1449:29;;1487:33;1514:5;1487:33;:::i;:::-;1387:139;;;;:::o;1532:474::-;1600:6;1608;1657:2;1645:9;1636:7;1632:23;1628:32;1625:119;;;1663:79;;:::i;:::-;1625:119;1783:1;1808:53;1853:7;1844:6;1833:9;1829:22;1808:53;:::i;:::-;1798:63;;1754:117;1910:2;1936:53;1981:7;1972:6;1961:9;1957:22;1936:53;:::i;:::-;1926:63;;1881:118;1532:474;;;;;:::o;2012:90::-;2046:7;2089:5;2082:13;2075:21;2064:32;;2012:90;;;:::o;2108:109::-;2189:21;2204:5;2189:21;:::i;:::-;2184:3;2177:34;2108:109;;:::o;2223:210::-;2310:4;2348:2;2337:9;2333:18;2325:26;;2361:65;2423:1;2412:9;2408:17;2399:6;2361:65;:::i;:::-;2223:210;;;;:::o;2439:117::-;2548:1;2545;2538:12;2562:117;2671:1;2668;2661:12;2685:117;2794:1;2791;2784:12;2821:552;2878:8;2888:6;2938:3;2931:4;2923:6;2919:17;2915:27;2905:122;;2946:79;;:::i;:::-;2905:122;3059:6;3046:20;3036:30;;3089:18;3081:6;3078:30;3075:117;;;3111:79;;:::i;:::-;3075:117;3225:4;3217:6;3213:17;3201:29;;3279:3;3271:4;3263:6;3259:17;3249:8;3245:32;3242:41;3239:128;;;3286:79;;:::i;:::-;3239:128;2821:552;;;;;:::o;3379:817::-;3467:6;3475;3483;3491;3540:2;3528:9;3519:7;3515:23;3511:32;3508:119;;;3546:79;;:::i;:::-;3508:119;3666:1;3691:53;3736:7;3727:6;3716:9;3712:22;3691:53;:::i;:::-;3681:63;;3637:117;3793:2;3819:53;3864:7;3855:6;3844:9;3840:22;3819:53;:::i;:::-;3809:63;;3764:118;3949:2;3938:9;3934:18;3921:32;3980:18;3972:6;3969:30;3966:117;;;4002:79;;:::i;:::-;3966:117;4115:64;4171:7;4162:6;4151:9;4147:22;4115:64;:::i;:::-;4097:82;;;;3892:297;3379:817;;;;;;;:::o;4202:118::-;4289:24;4307:5;4289:24;:::i;:::-;4284:3;4277:37;4202:118;;:::o;4326:222::-;4419:4;4457:2;4446:9;4442:18;4434:26;;4470:71;4538:1;4527:9;4523:17;4514:6;4470:71;:::i;:::-;4326:222;;;;:::o;4554:329::-;4613:6;4662:2;4650:9;4641:7;4637:23;4633:32;4630:119;;;4668:79;;:::i;:::-;4630:119;4788:1;4813:53;4858:7;4849:6;4838:9;4834:22;4813:53;:::i;:::-;4803:63;;4759:117;4554:329;;;;:::o;4889:118::-;4976:24;4994:5;4976:24;:::i;:::-;4971:3;4964:37;4889:118;;:::o;5013:222::-;5106:4;5144:2;5133:9;5129:18;5121:26;;5157:71;5225:1;5214:9;5210:17;5201:6;5157:71;:::i;:::-;5013:222;;;;:::o;5258:568::-;5331:8;5341:6;5391:3;5384:4;5376:6;5372:17;5368:27;5358:122;;5399:79;;:::i;:::-;5358:122;5512:6;5499:20;5489:30;;5542:18;5534:6;5531:30;5528:117;;;5564:79;;:::i;:::-;5528:117;5678:4;5670:6;5666:17;5654:29;;5732:3;5724:4;5716:6;5712:17;5702:8;5698:32;5695:41;5692:128;;;5739:79;;:::i;:::-;5692:128;5258:568;;;;;:::o;5832:559::-;5918:6;5926;5975:2;5963:9;5954:7;5950:23;5946:32;5943:119;;;5981:79;;:::i;:::-;5943:119;6129:1;6118:9;6114:17;6101:31;6159:18;6151:6;6148:30;6145:117;;;6181:79;;:::i;:::-;6145:117;6294:80;6366:7;6357:6;6346:9;6342:22;6294:80;:::i;:::-;6276:98;;;;6072:312;5832:559;;;;;:::o;6397:99::-;6449:6;6483:5;6477:12;6467:22;;6397:99;;;:::o;6502:169::-;6586:11;6620:6;6615:3;6608:19;6660:4;6655:3;6651:14;6636:29;;6502:169;;;;:::o;6677:246::-;6758:1;6768:113;6782:6;6779:1;6776:13;6768:113;;;6867:1;6862:3;6858:11;6852:18;6848:1;6843:3;6839:11;6832:39;6804:2;6801:1;6797:10;6792:15;;6768:113;;;6915:1;6906:6;6901:3;6897:16;6890:27;6739:184;6677:246;;;:::o;6929:102::-;6970:6;7021:2;7017:7;7012:2;7005:5;7001:14;6997:28;6987:38;;6929:102;;;:::o;7037:377::-;7125:3;7153:39;7186:5;7153:39;:::i;:::-;7208:71;7272:6;7267:3;7208:71;:::i;:::-;7201:78;;7288:65;7346:6;7341:3;7334:4;7327:5;7323:16;7288:65;:::i;:::-;7378:29;7400:6;7378:29;:::i;:::-;7373:3;7369:39;7362:46;;7129:285;7037:377;;;;:::o;7420:313::-;7533:4;7571:2;7560:9;7556:18;7548:26;;7620:9;7614:4;7610:20;7606:1;7595:9;7591:17;7584:47;7648:78;7721:4;7712:6;7648:78;:::i;:::-;7640:86;;7420:313;;;;:::o;7739:60::-;7767:3;7788:5;7781:12;;7739:60;;;:::o;7805:142::-;7855:9;7888:53;7906:34;7915:24;7933:5;7915:24;:::i;:::-;7906:34;:::i;:::-;7888:53;:::i;:::-;7875:66;;7805:142;;;:::o;7953:126::-;8003:9;8036:37;8067:5;8036:37;:::i;:::-;8023:50;;7953:126;;;:::o;8085:141::-;8150:9;8183:37;8214:5;8183:37;:::i;:::-;8170:50;;8085:141;;;:::o;8232:161::-;8334:52;8380:5;8334:52;:::i;:::-;8329:3;8322:65;8232:161;;:::o;8399:252::-;8507:4;8545:2;8534:9;8530:18;8522:26;;8558:86;8641:1;8630:9;8626:17;8617:6;8558:86;:::i;:::-;8399:252;;;;:::o;8657:145::-;8726:9;8759:37;8790:5;8759:37;:::i;:::-;8746:50;;8657:145;;;:::o;8808:169::-;8914:56;8964:5;8914:56;:::i;:::-;8909:3;8902:69;8808:169;;:::o;8983:260::-;9095:4;9133:2;9122:9;9118:18;9110:26;;9146:90;9233:1;9222:9;9218:17;9209:6;9146:90;:::i;:::-;8983:260;;;;:::o;9249:934::-;9371:6;9379;9387;9395;9444:2;9432:9;9423:7;9419:23;9415:32;9412:119;;;9450:79;;:::i;:::-;9412:119;9598:1;9587:9;9583:17;9570:31;9628:18;9620:6;9617:30;9614:117;;;9650:79;;:::i;:::-;9614:117;9763:80;9835:7;9826:6;9815:9;9811:22;9763:80;:::i;:::-;9745:98;;;;9541:312;9920:2;9909:9;9905:18;9892:32;9951:18;9943:6;9940:30;9937:117;;;9973:79;;:::i;:::-;9937:117;10086:80;10158:7;10149:6;10138:9;10134:22;10086:80;:::i;:::-;10068:98;;;;9863:313;9249:934;;;;;;;:::o;10189:140::-;10253:9;10286:37;10317:5;10286:37;:::i;:::-;10273:50;;10189:140;;;:::o;10335:159::-;10436:51;10481:5;10436:51;:::i;:::-;10431:3;10424:64;10335:159;;:::o;10500:250::-;10607:4;10645:2;10634:9;10630:18;10622:26;;10658:85;10740:1;10729:9;10725:17;10716:6;10658:85;:::i;:::-;10500:250;;;;:::o;10756:114::-;10823:6;10857:5;10851:12;10841:22;;10756:114;;;:::o;10876:184::-;10975:11;11009:6;11004:3;10997:19;11049:4;11044:3;11040:14;11025:29;;10876:184;;;;:::o;11066:132::-;11133:4;11156:3;11148:11;;11186:4;11181:3;11177:14;11169:22;;11066:132;;;:::o;11204:108::-;11281:24;11299:5;11281:24;:::i;:::-;11276:3;11269:37;11204:108;;:::o;11318:179::-;11387:10;11408:46;11450:3;11442:6;11408:46;:::i;:::-;11486:4;11481:3;11477:14;11463:28;;11318:179;;;;:::o;11503:113::-;11573:4;11605;11600:3;11596:14;11588:22;;11503:113;;;:::o;11652:732::-;11771:3;11800:54;11848:5;11800:54;:::i;:::-;11870:86;11949:6;11944:3;11870:86;:::i;:::-;11863:93;;11980:56;12030:5;11980:56;:::i;:::-;12059:7;12090:1;12075:284;12100:6;12097:1;12094:13;12075:284;;;12176:6;12170:13;12203:63;12262:3;12247:13;12203:63;:::i;:::-;12196:70;;12289:60;12342:6;12289:60;:::i;:::-;12279:70;;12135:224;12122:1;12119;12115:9;12110:14;;12075:284;;;12079:14;12375:3;12368:10;;11776:608;;;11652:732;;;;:::o;12390:373::-;12533:4;12571:2;12560:9;12556:18;12548:26;;12620:9;12614:4;12610:20;12606:1;12595:9;12591:17;12584:47;12648:108;12751:4;12742:6;12648:108;:::i;:::-;12640:116;;12390:373;;;;:::o;12769:145::-;12838:9;12871:37;12902:5;12871:37;:::i;:::-;12858:50;;12769:145;;;:::o;12920:169::-;13026:56;13076:5;13026:56;:::i;:::-;13021:3;13014:69;12920:169;;:::o;13095:260::-;13207:4;13245:2;13234:9;13230:18;13222:26;;13258:90;13345:1;13334:9;13330:17;13321:6;13258:90;:::i;:::-;13095:260;;;;:::o;13361:817::-;13449:6;13457;13465;13473;13522:2;13510:9;13501:7;13497:23;13493:32;13490:119;;;13528:79;;:::i;:::-;13490:119;13648:1;13673:53;13718:7;13709:6;13698:9;13694:22;13673:53;:::i;:::-;13663:63;;13619:117;13803:2;13792:9;13788:18;13775:32;13834:18;13826:6;13823:30;13820:117;;;13856:79;;:::i;:::-;13820:117;13969:64;14025:7;14016:6;14005:9;14001:22;13969:64;:::i;:::-;13951:82;;;;13746:297;14082:2;14108:53;14153:7;14144:6;14133:9;14129:22;14108:53;:::i;:::-;14098:63;;14053:118;13361:817;;;;;;;:::o;14184:111::-;14269:1;14262:5;14259:12;14249:40;;14285:1;14282;14275:12;14249:40;14184:111;:::o;14301:163::-;14359:5;14397:6;14384:20;14375:29;;14413:45;14452:5;14413:45;:::i;:::-;14301:163;;;;:::o;14470:498::-;14550:6;14558;14607:2;14595:9;14586:7;14582:23;14578:32;14575:119;;;14613:79;;:::i;:::-;14575:119;14733:1;14758:65;14815:7;14806:6;14795:9;14791:22;14758:65;:::i;:::-;14748:75;;14704:129;14872:2;14898:53;14943:7;14934:6;14923:9;14919:22;14898:53;:::i;:::-;14888:63;;14843:118;14470:498;;;;;:::o;14974:143::-;15031:5;15062:6;15056:13;15047:22;;15078:33;15105:5;15078:33;:::i;:::-;14974:143;;;;:::o;15123:351::-;15193:6;15242:2;15230:9;15221:7;15217:23;15213:32;15210:119;;;15248:79;;:::i;:::-;15210:119;15368:1;15393:64;15449:7;15440:6;15429:9;15425:22;15393:64;:::i;:::-;15383:74;;15339:128;15123:351;;;;:::o;15480:180::-;15528:77;15525:1;15518:88;15625:4;15622:1;15615:15;15649:4;15646:1;15639:15;15666:117;15775:1;15772;15765:12;15789:180;15837:77;15834:1;15827:88;15934:4;15931:1;15924:15;15958:4;15955:1;15948:15;15975:281;16058:27;16080:4;16058:27;:::i;:::-;16050:6;16046:40;16188:6;16176:10;16173:22;16152:18;16140:10;16137:34;16134:62;16131:88;;;16199:18;;:::i;:::-;16131:88;16239:10;16235:2;16228:22;16018:238;15975:281;;:::o;16262:129::-;16296:6;16323:20;;:::i;:::-;16313:30;;16352:33;16380:4;16372:6;16352:33;:::i;:::-;16262:129;;;:::o;16397:117::-;16506:1;16503;16496:12;16520:117;16629:1;16626;16619:12;16643:308;16705:4;16795:18;16787:6;16784:30;16781:56;;;16817:18;;:::i;:::-;16781:56;16855:29;16877:6;16855:29;:::i;:::-;16847:37;;16939:4;16933;16929:15;16921:23;;16643:308;;;:::o;16957:434::-;17046:5;17071:66;17087:49;17129:6;17087:49;:::i;:::-;17071:66;:::i;:::-;17062:75;;17160:6;17153:5;17146:21;17198:4;17191:5;17187:16;17236:3;17227:6;17222:3;17218:16;17215:25;17212:112;;;17243:79;;:::i;:::-;17212:112;17333:52;17378:6;17373:3;17368;17333:52;:::i;:::-;17052:339;16957:434;;;;;:::o;17411:355::-;17478:5;17527:3;17520:4;17512:6;17508:17;17504:27;17494:122;;17535:79;;:::i;:::-;17494:122;17645:6;17639:13;17670:90;17756:3;17748:6;17741:4;17733:6;17729:17;17670:90;:::i;:::-;17661:99;;17484:282;17411:355;;;;:::o;17772:111::-;17857:1;17850:5;17847:12;17837:40;;17873:1;17870;17863:12;17837:40;17772:111;:::o;17889:167::-;17958:5;17989:6;17983:13;17974:22;;18005:45;18044:5;18005:45;:::i;:::-;17889:167;;;;:::o;18062:::-;18131:5;18162:6;18156:13;18147:22;;18178:45;18217:5;18178:45;:::i;:::-;18062:167;;;;:::o;18235:89::-;18271:7;18311:6;18304:5;18300:18;18289:29;;18235:89;;;:::o;18330:120::-;18402:23;18419:5;18402:23;:::i;:::-;18395:5;18392:34;18382:62;;18440:1;18437;18430:12;18382:62;18330:120;:::o;18456:141::-;18512:5;18543:6;18537:13;18528:22;;18559:32;18585:5;18559:32;:::i;:::-;18456:141;;;;:::o;18628:943::-;18710:5;18754:4;18742:9;18737:3;18733:19;18729:30;18726:117;;;18762:79;;:::i;:::-;18726:117;18861:21;18877:4;18861:21;:::i;:::-;18852:30;;18939:1;18979:60;19035:3;19026:6;19015:9;19011:22;18979:60;:::i;:::-;18972:4;18965:5;18961:16;18954:86;18892:159;19109:2;19150:60;19206:3;19197:6;19186:9;19182:22;19150:60;:::i;:::-;19143:4;19136:5;19132:16;19125:86;19061:161;19280:2;19321:60;19377:3;19368:6;19357:9;19353:22;19321:60;:::i;:::-;19314:4;19307:5;19303:16;19296:86;19232:161;19451:2;19492:60;19548:3;19539:6;19528:9;19524:22;19492:60;:::i;:::-;19485:4;19478:5;19474:16;19467:86;19403:161;18628:943;;;;:::o;19577:310::-;19653:4;19743:18;19735:6;19732:30;19729:56;;;19765:18;;:::i;:::-;19729:56;19815:4;19807:6;19803:17;19795:25;;19875:4;19869;19865:15;19857:23;;19577:310;;;:::o;19909:729::-;20015:5;20040:80;20056:63;20112:6;20056:63;:::i;:::-;20040:80;:::i;:::-;20031:89;;20140:5;20169:6;20162:5;20155:21;20203:4;20196:5;20192:16;20185:23;;20256:4;20248:6;20244:17;20236:6;20232:30;20285:3;20277:6;20274:15;20271:122;;;20304:79;;:::i;:::-;20271:122;20419:6;20402:230;20436:6;20431:3;20428:15;20402:230;;;20511:3;20540:47;20583:3;20571:10;20540:47;:::i;:::-;20535:3;20528:60;20617:4;20612:3;20608:14;20601:21;;20478:154;20462:4;20457:3;20453:14;20446:21;;20402:230;;;20406:21;20021:617;;19909:729;;;;;:::o;20660:383::-;20741:5;20790:3;20783:4;20775:6;20771:17;20767:27;20757:122;;20798:79;;:::i;:::-;20757:122;20908:6;20902:13;20933:104;21033:3;21025:6;21018:4;21010:6;21006:17;20933:104;:::i;:::-;20924:113;;20747:296;20660:383;;;;:::o;21077:2043::-;21162:5;21206:6;21194:9;21189:3;21185:19;21181:32;21178:119;;;21216:79;;:::i;:::-;21178:119;21315:21;21331:4;21315:21;:::i;:::-;21306:30;;21416:1;21405:9;21401:17;21395:24;21446:18;21438:6;21435:30;21432:117;;;21468:79;;:::i;:::-;21432:117;21588:70;21654:3;21645:6;21634:9;21630:22;21588:70;:::i;:::-;21581:4;21574:5;21570:16;21563:96;21346:324;21754:2;21743:9;21739:18;21733:25;21785:18;21777:6;21774:30;21771:117;;;21807:79;;:::i;:::-;21771:117;21927:70;21993:3;21984:6;21973:9;21969:22;21927:70;:::i;:::-;21920:4;21913:5;21909:16;21902:96;21680:329;22072:2;22113:72;22181:3;22172:6;22161:9;22157:22;22113:72;:::i;:::-;22106:4;22099:5;22095:16;22088:98;22019:178;22260:2;22301:72;22369:3;22360:6;22349:9;22345:22;22301:72;:::i;:::-;22294:4;22287:5;22283:16;22276:98;22207:178;22448:3;22490:59;22545:3;22536:6;22525:9;22521:22;22490:59;:::i;:::-;22483:4;22476:5;22472:16;22465:85;22395:166;22621:3;22663:82;22741:3;22732:6;22721:9;22717:22;22663:82;:::i;:::-;22656:4;22649:5;22645:16;22638:108;22571:186;22843:3;22832:9;22828:19;22822:26;22875:18;22867:6;22864:30;22861:117;;;22897:79;;:::i;:::-;22861:117;23017:84;23097:3;23088:6;23077:9;23073:22;23017:84;:::i;:::-;23010:4;23003:5;22999:16;22992:110;22767:346;21077:2043;;;;:::o;23126:554::-;23221:6;23270:2;23258:9;23249:7;23245:23;23241:32;23238:119;;;23276:79;;:::i;:::-;23238:119;23417:1;23406:9;23402:17;23396:24;23447:18;23439:6;23436:30;23433:117;;;23469:79;;:::i;:::-;23433:117;23574:89;23655:7;23646:6;23635:9;23631:22;23574:89;:::i;:::-;23564:99;;23367:306;23126:554;;;;:::o;23686:94::-;23719:8;23767:5;23763:2;23759:14;23738:35;;23686:94;;;:::o;23786:::-;23825:7;23854:20;23868:5;23854:20;:::i;:::-;23843:31;;23786:94;;;:::o;23886:100::-;23925:7;23954:26;23974:5;23954:26;:::i;:::-;23943:37;;23886:100;;;:::o;23992:157::-;24097:45;24117:24;24135:5;24117:24;:::i;:::-;24097:45;:::i;:::-;24092:3;24085:58;23992:157;;:::o;24155:79::-;24194:7;24223:5;24212:16;;24155:79;;;:::o;24240:157::-;24345:45;24365:24;24383:5;24365:24;:::i;:::-;24345:45;:::i;:::-;24340:3;24333:58;24240:157;;:::o;24403:148::-;24505:11;24542:3;24527:18;;24403:148;;;;:::o;24557:152::-;24697:4;24693:1;24685:6;24681:14;24674:28;24557:152;:::o;24715:400::-;24875:3;24896:84;24978:1;24973:3;24896:84;:::i;:::-;24889:91;;24989:93;25078:3;24989:93;:::i;:::-;25107:1;25102:3;25098:11;25091:18;;24715:400;;;:::o;25121:804::-;25390:3;25405:75;25476:3;25467:6;25405:75;:::i;:::-;25505:2;25500:3;25496:12;25489:19;;25518:75;25589:3;25580:6;25518:75;:::i;:::-;25618:2;25613:3;25609:12;25602:19;;25631:75;25702:3;25693:6;25631:75;:::i;:::-;25731:2;25726:3;25722:12;25715:19;;25751:148;25895:3;25751:148;:::i;:::-;25744:155;;25916:3;25909:10;;25121:804;;;;;;:::o;25931:180::-;25979:77;25976:1;25969:88;26076:4;26073:1;26066:15;26100:4;26097:1;26090:15;26117:104;26182:6;26210:4;26200:14;;26117:104;;;:::o;26227:143::-;26324:11;26361:3;26346:18;;26227:143;;;;:::o;26376:98::-;26441:4;26464:3;26456:11;;26376:98;;;:::o;26480:111::-;26548:4;26580;26575:3;26571:14;26563:22;;26480:111;;;:::o;26629:694::-;26765:52;26811:5;26765:52;:::i;:::-;26833:84;26910:6;26905:3;26833:84;:::i;:::-;26826:91;;26941:54;26989:5;26941:54;:::i;:::-;27018:7;27049:1;27034:282;27059:6;27056:1;27053:13;27034:282;;;27135:6;27129:13;27162:63;27221:3;27206:13;27162:63;:::i;:::-;27155:70;;27248:58;27299:6;27248:58;:::i;:::-;27238:68;;27094:222;27081:1;27078;27074:9;27069:14;;27034:282;;;27038:14;26741:582;;;26629:694;;:::o;27329:687::-;27574:4;27612:3;27601:9;27597:19;27589:27;;27662:9;27656:4;27652:20;27648:1;27637:9;27633:17;27626:47;27690:108;27793:4;27784:6;27690:108;:::i;:::-;27682:116;;27808:118;27922:2;27911:9;27907:18;27898:6;27808:118;:::i;:::-;27936:73;28004:3;27993:9;27989:19;27980:6;27936:73;:::i;:::-;27329:687;;;;;;:::o;28022:180::-;28070:77;28067:1;28060:88;28167:4;28164:1;28157:15;28191:4;28188:1;28181:15;28208:176;28240:1;28257:20;28275:1;28257:20;:::i;:::-;28252:25;;28291:20;28309:1;28291:20;:::i;:::-;28286:25;;28330:1;28320:35;;28335:18;;:::i;:::-;28320:35;28376:1;28373;28369:9;28364:14;;28208:176;;;;:::o;28390:180::-;28438:77;28435:1;28428:88;28535:4;28532:1;28525:15;28559:4;28556:1;28549:15;28576:185;28616:1;28633:20;28651:1;28633:20;:::i;:::-;28628:25;;28667:20;28685:1;28667:20;:::i;:::-;28662:25;;28706:1;28696:35;;28711:18;;:::i;:::-;28696:35;28753:1;28750;28746:9;28741:14;;28576:185;;;;:::o;28767:410::-;28807:7;28830:20;28848:1;28830:20;:::i;:::-;28825:25;;28864:20;28882:1;28864:20;:::i;:::-;28859:25;;28919:1;28916;28912:9;28941:30;28959:11;28941:30;:::i;:::-;28930:41;;29120:1;29111:7;29107:15;29104:1;29101:22;29081:1;29074:9;29054:83;29031:139;;29150:18;;:::i;:::-;29031:139;28815:362;28767:410;;;;:::o;29183:191::-;29223:3;29242:20;29260:1;29242:20;:::i;:::-;29237:25;;29276:20;29294:1;29276:20;:::i;:::-;29271:25;;29319:1;29316;29312:9;29305:16;;29340:3;29337:1;29334:10;29331:36;;;29347:18;;:::i;:::-;29331:36;29183:191;;;;:::o;29380:143::-;29437:5;29468:6;29462:13;29453:22;;29484:33;29511:5;29484:33;:::i;:::-;29380:143;;;;:::o;29529:351::-;29599:6;29648:2;29636:9;29627:7;29623:23;29619:32;29616:119;;;29654:79;;:::i;:::-;29616:119;29774:1;29799:64;29855:7;29846:6;29835:9;29831:22;29799:64;:::i;:::-;29789:74;;29745:128;29529:351;;;;:::o;29886:249::-;29961:4;30051:18;30043:6;30040:30;30037:56;;;30073:18;;:::i;:::-;30037:56;30123:4;30115:6;30111:17;30103:25;;29886:249;;;:::o;30159:665::-;30264:5;30289:79;30305:62;30360:6;30305:62;:::i;:::-;30289:79;:::i;:::-;30280:88;;30388:5;30441:4;30433:6;30429:17;30421:6;30417:30;30470:3;30462:6;30459:15;30456:122;;;30489:79;;:::i;:::-;30456:122;30604:6;30587:231;30621:6;30616:3;30613:15;30587:231;;;30696:3;30725:48;30769:3;30757:10;30725:48;:::i;:::-;30720:3;30713:61;30803:4;30798:3;30794:14;30787:21;;30663:155;30647:4;30642:3;30638:14;30631:21;;30587:231;;;30591:21;30270:554;;30159:665;;;;;:::o;30848:361::-;30928:5;30977:3;30970:4;30962:6;30958:17;30954:27;30944:122;;30985:79;;:::i;:::-;30944:122;31089:4;31111:92;31199:3;31191:6;31183;31111:92;:::i;:::-;31102:101;;30934:275;30848:361;;;;:::o;31245:2109::-;31332:5;31376:6;31364:9;31359:3;31355:19;31351:32;31348:119;;;31386:79;;:::i;:::-;31348:119;31485:23;31501:6;31485:23;:::i;:::-;31476:32;;31573:1;31613:60;31669:3;31660:6;31649:9;31645:22;31613:60;:::i;:::-;31606:4;31599:5;31595:16;31588:86;31518:167;31752:2;31793:60;31849:3;31840:6;31829:9;31825:22;31793:60;:::i;:::-;31786:4;31779:5;31775:16;31768:86;31695:170;31925:2;31966:60;32022:3;32013:6;32002:9;31998:22;31966:60;:::i;:::-;31959:4;31952:5;31948:16;31941:86;31875:163;32101:2;32142:72;32210:3;32201:6;32190:9;32186:22;32142:72;:::i;:::-;32135:4;32128:5;32124:16;32117:98;32048:178;32289:3;32331:72;32399:3;32390:6;32379:9;32375:22;32331:72;:::i;:::-;32324:4;32317:5;32313:16;32306:98;32236:179;32478:3;32520:59;32575:3;32566:6;32555:9;32551:22;32520:59;:::i;:::-;32513:4;32506:5;32502:16;32495:85;32425:166;32651:3;32693:82;32771:3;32762:6;32751:9;32747:22;32693:82;:::i;:::-;32686:4;32679:5;32675:16;32668:108;32601:186;32873:3;32862:9;32858:19;32852:26;32905:18;32897:6;32894:30;32891:117;;;32927:79;;:::i;:::-;32891:117;33047:84;33127:3;33118:6;33107:9;33103:22;33047:84;:::i;:::-;33040:4;33033:5;33029:16;33022:110;32797:346;33208:3;33252:83;33331:3;33322:6;33311:9;33307:22;33252:83;:::i;:::-;33243:6;33236:5;33232:18;33225:111;33153:194;31245:2109;;;;:::o;33360:558::-;33457:6;33506:2;33494:9;33485:7;33481:23;33477:32;33474:119;;;33512:79;;:::i;:::-;33474:119;33653:1;33642:9;33638:17;33632:24;33683:18;33675:6;33672:30;33669:117;;;33705:79;;:::i;:::-;33669:117;33810:91;33893:7;33884:6;33873:9;33869:22;33810:91;:::i;:::-;33800:101;;33603:308;33360:558;;;;:::o;33924:397::-;34064:3;34079:75;34150:3;34141:6;34079:75;:::i;:::-;34179:2;34174:3;34170:12;34163:19;;34192:75;34263:3;34254:6;34192:75;:::i;:::-;34292:2;34287:3;34283:12;34276:19;;34312:3;34305:10;;33924:397;;;;;:::o;34327:233::-;34366:3;34389:24;34407:5;34389:24;:::i;:::-;34380:33;;34435:66;34428:5;34425:77;34422:103;;34505:18;;:::i;:::-;34422:103;34552:1;34545:5;34541:13;34534:20;;34327:233;;;:::o;34566:117::-;34675:1;34672;34665:12;34689:98;34773:6;34768:3;34763;34750:30;34689:98;;;:::o;34823:537::-;34951:3;34972:86;35051:6;35046:3;34972:86;:::i;:::-;34965:93;;35082:66;35074:6;35071:78;35068:165;;;35152:79;;:::i;:::-;35068:165;35264:4;35256:6;35252:17;35242:27;;35279:43;35315:6;35310:3;35303:5;35279:43;:::i;:::-;35347:6;35342:3;35338:16;35331:23;;34823:537;;;;;:::o;35366:393::-;35519:4;35557:2;35546:9;35542:18;35534:26;;35606:9;35600:4;35596:20;35592:1;35581:9;35577:17;35570:47;35634:118;35747:4;35738:6;35730;35634:118;:::i;:::-;35626:126;;35366:393;;;;;:::o;35765:117::-;35850:1;35843:5;35840:12;35830:46;;35856:18;;:::i;:::-;35830:46;35765:117;:::o;35888:135::-;35937:7;35966:5;35955:16;;35972:45;36011:5;35972:45;:::i;:::-;35888:135;;;:::o;36029:::-;36089:9;36122:36;36152:5;36122:36;:::i;:::-;36109:49;;36029:135;;;:::o;36170:151::-;36267:47;36308:5;36267:47;:::i;:::-;36262:3;36255:60;36170:151;;:::o;36327:462::-;36486:4;36524:2;36513:9;36509:18;36501:26;;36537:81;36615:1;36604:9;36600:17;36591:6;36537:81;:::i;:::-;36628:72;36696:2;36685:9;36681:18;36672:6;36628:72;:::i;:::-;36710;36778:2;36767:9;36763:18;36754:6;36710:72;:::i;:::-;36327:462;;;;;;:::o;36795:111::-;36859:6;36893:5;36887:12;36877:22;;36795:111;;;:::o;36912:156::-;36976:4;36999:3;36991:11;;37022:3;37019:1;37012:14;37056:4;37053:1;37043:18;37035:26;;36912:156;;;:::o;37074:102::-;37116:8;37163:5;37160:1;37156:13;37135:34;;37074:102;;;:::o;37182:90::-;37232:7;37261:5;37250:16;;37182:90;;;:::o;37278:166::-;37347:5;37372:66;37403:34;37426:10;37403:34;:::i;:::-;37372:66;:::i;:::-;37363:75;;37278:166;;;:::o;37450:144::-;37505:5;37530:57;37581:4;37575:11;37530:57;:::i;:::-;37521:66;;37450:144;;;:::o;37600:110::-;37667:4;37699;37694:3;37690:14;37682:22;;37600:110;;;:::o;37746:751::-;37862:3;37891:51;37936:5;37891:51;:::i;:::-;37958:86;38037:6;38032:3;37958:86;:::i;:::-;37951:93;;38068:53;38115:5;38068:53;:::i;:::-;38144:7;38175:1;38160:312;38185:6;38182:1;38179:13;38160:312;;;38255:44;38292:6;38255:44;:::i;:::-;38319:63;38378:3;38363:13;38319:63;:::i;:::-;38312:70;;38405:57;38455:6;38405:57;:::i;:::-;38395:67;;38220:252;38207:1;38204;38200:9;38195:14;;38160:312;;;38164:14;38488:3;38481:10;;37867:630;;;37746:751;;;;:::o;38503:648::-;38731:4;38769:2;38758:9;38754:18;38746:26;;38818:9;38812:4;38808:20;38804:1;38793:9;38789:17;38782:47;38846:118;38959:4;38950:6;38942;38846:118;:::i;:::-;38838:126;;39011:9;39005:4;39001:20;38996:2;38985:9;38981:18;38974:48;39039:105;39139:4;39130:6;39039:105;:::i;:::-;39031:113;;38503:648;;;;;;:::o;39157:152::-;39297:4;39293:1;39285:6;39281:14;39274:28;39157:152;:::o;39315:400::-;39475:3;39496:84;39578:1;39573:3;39496:84;:::i;:::-;39489:91;;39589:93;39678:3;39589:93;:::i;:::-;39707:1;39702:3;39698:11;39691:18;;39315:400;;;:::o;39721:804::-;39990:3;40005:75;40076:3;40067:6;40005:75;:::i;:::-;40105:2;40100:3;40096:12;40089:19;;40118:75;40189:3;40180:6;40118:75;:::i;:::-;40218:2;40213:3;40209:12;40202:19;;40231:75;40302:3;40293:6;40231:75;:::i;:::-;40331:2;40326:3;40322:12;40315:19;;40351:148;40495:3;40351:148;:::i;:::-;40344:155;;40516:3;40509:10;;39721:804;;;;;;:::o;40531:194::-;40571:4;40591:20;40609:1;40591:20;:::i;:::-;40586:25;;40625:20;40643:1;40625:20;:::i;:::-;40620:25;;40669:1;40666;40662:9;40654:17;;40693:1;40687:4;40684:11;40681:37;;;40698:18;;:::i;:::-;40681:37;40531:194;;;;:::o;40731:147::-;40832:11;40869:3;40854:18;;40731:147;;;;:::o;40884:146::-;40981:6;40976:3;40971;40958:30;41022:1;41013:6;41008:3;41004:16;40997:27;40884:146;;;:::o;41058:327::-;41172:3;41193:88;41274:6;41269:3;41193:88;:::i;:::-;41186:95;;41291:56;41340:6;41335:3;41328:5;41291:56;:::i;:::-;41372:6;41367:3;41363:16;41356:23;;41058:327;;;;;:::o;41391:291::-;41531:3;41553:103;41652:3;41643:6;41635;41553:103;:::i;:::-;41546:110;;41673:3;41666:10;;41391:291;;;;;:::o
Swarm Source
ipfs://775d7d8a97fbf134477b26bff9f1fa4d72c0b775fb41d99a20cd7c2e9dce1f92
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 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.