Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Intractopia
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
contract IntractopiaStorage {
/* ============ TypeHashes and Constants ============ */
bytes32 public constant ERC1155_CLAIM_TYPEHASH = keccak256(
"ERC1155Claim(uint96 rewardId,uint96 userId,uint256 tokenId,address userAddress,uint256 amountToClaim)"
);
bytes32 public constant ERC1155_DUMMY_CLAIM_TYPEHASH = keccak256(
"ERC1155DummyClaim(uint96 rewardId,uint96 userId,address userAddress)"
);
/* ============ Events ============ */
event ERC1155SignerUpdate(address oldSigner, address newSigner);
event ERC1155AdminAdded(uint256 tokenId, address admin);
event ERC1155CollectionLaunch(
uint256 indexed tokenId,
address indexed creator,
uint256 initialSupply
);
event ERC1155Claim(
uint96 rewardId,
uint96 indexed userId,
uint256 indexed tokenId,
address indexed userAddress,
uint256 amountToClaim
);
event ERC1155DummyClaim(
uint96 indexed rewardId,
uint96 indexed userId,
address userAddress
);
/* ============ Structs ============ */
/* ============ State Variables ============ */
// Intract Signer
address public intractSigner;
// TokenId
uint256 public currentTokenId;
// Mapping from tokenId to creator address
mapping (uint256 => address) public creator;
// Mapping from tokenId to admin addresses
mapping (uint256 => mapping (address => bool)) public isAdmin;
// Mapping from tokenId to current token supply
mapping (uint256 => uint256) public tokenSupply;
// rewardId => userAddress => if he has claimed
mapping(uint96 => mapping(address => bool)) public hasClaimed;
// rewardId => userId => if he has claimed
mapping(uint96 => mapping(uint96 => bool)) public hasClaimedUserId;
// signature => if it has been used
mapping(bytes32 => bool) public usedDummyClaimHashes;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contract Intractopia is Initializable, OwnableUpgradeable, PausableUpgradeable, EIP712Upgradeable, ReentrancyGuardUpgradeable, ERC1155Upgradeable, ERC2771ContextUpgradeable, IntractopiaStorage {
/* ============ Modifiers ============ */
modifier tokenExists(uint256 _tokenId) {
require(creator[_tokenId] != address(0), "Intractopia: TokenId does not exist");
_;
}
modifier onlyAdmin(uint256 _tokenId) {
require(isAdmin[_tokenId][_msgSender()], "Intractopia: Only admin can call this function");
_;
}
/* ============ Initial setup ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) ERC2771ContextUpgradeable(_trustedForwarder) {}
function initialize(address _intractSigner, string calldata _uri) external initializer {
require(_intractSigner != address(0), "Intractopia: Intract signer address must not be null address");
__Ownable_init();
__Pausable_init();
__EIP712_init("Intractopia", "1.0.0");
__ReentrancyGuard_init();
__ERC1155_init(_uri);
intractSigner = _intractSigner;
currentTokenId = 1;
uint256 _id = currentTokenId;
creator[_id] = _msgSender();
isAdmin[_id][_msgSender()] = true;
_mint(_msgSender(), _id, 1, "");
tokenSupply[_id] = 1;
emit ERC1155SignerUpdate(address(0), _intractSigner);
}
/* ============ External Functions ============ */
function createCollection(
uint256 _initialSupply
) external virtual whenNotPaused nonReentrant returns (uint256) {
currentTokenId += 1;
uint256 _id = currentTokenId;
creator[_id] = _msgSender();
isAdmin[_id][_msgSender()] = true;
_mint(_msgSender(), _id, _initialSupply, "");
tokenSupply[_id] = _initialSupply;
emit ERC1155CollectionLaunch(_id, _msgSender(), _initialSupply);
return _id;
}
function claim(
uint96 _rewardId,
uint96 _userId,
uint256 _tokenId,
uint256 _amountToClaim,
address _userAddress,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant tokenExists(_tokenId) {
require(_rewardId > 0, "Intractopia: Invalid rewardId");
require(_userId > 0, "Intractopia: Invalid userId");
require(_tokenId > 0, "Intractopia: Invalid tokenId");
require(_amountToClaim > 0, "Intractopia: Invalid amount");
require(_userAddress != address(0), "Intractopia: Invalid userAddress");
require(!hasClaimed[_rewardId][_userAddress], "Intractopia: Already claimed");
require(!hasClaimedUserId[_rewardId][_userId], "Intractopia: Already claimed");
require(_verify(
_hashClaim(_rewardId, _userId, _tokenId, _userAddress, _amountToClaim),
_signature
), "Intractopia: Invalid signature");
hasClaimed[_rewardId][_userAddress] = true;
hasClaimedUserId[_rewardId][_userId] = true;
emit ERC1155Claim(_rewardId, _userId, _tokenId, _userAddress, _amountToClaim);
tokenSupply[_tokenId] += _amountToClaim;
_mint(_userAddress, _tokenId, _amountToClaim, "");
}
function dummyClaim(
uint96 _rewardId,
uint96 _userId,
address _userAddress,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_rewardId > 0, "Intractopia: Invalid rewardId");
require(_userId > 0, "Intractopia: Invalid userId");
require(_userAddress != address(0), "Intractopia: Invalid userAddress");
bytes32 hash = _hashDummyClaim(_rewardId, _userId, _userAddress);
require(!usedDummyClaimHashes[hash], "Intractopia: Already claimed");
uint256 amountToClaim = 1;
uint256 tokenId = 1;
require(_verify(
hash,
_signature
), "Intractopia: Invalid signature");
usedDummyClaimHashes[hash] = true;
emit ERC1155DummyClaim(_rewardId, _userId, _userAddress);
tokenSupply[tokenId] += amountToClaim;
_mint(_userAddress, tokenId, amountToClaim, "");
}
function uri(uint256 _tokenId) public virtual override view returns (string memory) {
return string(abi.encodePacked(super.uri(_tokenId), StringsUpgradeable.toString(_tokenId), ".json"));
}
/* ============ Owner Functions ============ */
function updateSigner(address _intractSigner) external onlyOwner {
require(_intractSigner != address(0), "Intractopia: Invalid address");
emit ERC1155SignerUpdate(intractSigner, _intractSigner);
intractSigner = _intractSigner;
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function setURI(string memory _uri) public onlyOwner {
_setURI(_uri);
}
/* ============ Token Admin Functions ============ */
function mint(
address _to,
uint256 _tokenId,
uint256 _amount,
bytes memory _data
) external virtual nonReentrant onlyAdmin(_tokenId) {
tokenSupply[_tokenId] += _amount;
super._mint(_to, _tokenId, _amount, _data);
}
function mintBatch(
address _to,
uint256[] memory _tokenIds,
uint256[] memory _amounts,
bytes memory _data
) external virtual nonReentrant {
for (uint256 i = 0; i < _tokenIds.length; i++) {
uint256 id = _tokenIds[i];
require(isAdmin[id][_msgSender()], "Intractopia: Only admin can call this function");
tokenSupply[id] += _amounts[i];
}
super._mintBatch(_to, _tokenIds, _amounts, _data);
}
function addAdmin(uint256 _tokenId, address _admin) external virtual onlyAdmin(_tokenId) {
require(_admin != address(0), "Intractopia: Invalid address");
isAdmin[_tokenId][_admin] = true;
emit ERC1155AdminAdded(_tokenId, _admin);
}
/* ============ Fallback Functions ============ */
receive() external payable {
// anonymous transfer: to admin
(bool success, ) = payable(owner()).call{value: msg.value}(
new bytes(0)
);
require(success, "Intractopia: Transfer failed");
}
fallback() external payable {
if (msg.value > 0) {
// call non exist function: send to admin
(bool success, ) = payable(owner()).call{value: msg.value}(new bytes(0));
require(success, "Intractopia: Transfer failed");
}
}
/* ============ Internal Functions ============ */
function _hashClaim(
uint96 _rewardId,
uint96 _userId,
uint256 _tokenId,
address _userAddress,
uint256 _amountToClaim
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC1155_CLAIM_TYPEHASH,
_rewardId,
_userId,
_tokenId,
_userAddress,
_amountToClaim
)
)
);
}
function _hashDummyClaim(
uint96 _rewardId,
uint96 _userId,
address _userAddress
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC1155_DUMMY_CLAIM_TYPEHASH,
_rewardId,
_userId,
_userAddress
)
)
);
}
function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
function _verify(bytes32 hash, bytes calldata signature) internal view returns (bool) {
return ECDSA.recover(hash, signature) == intractSigner;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)
pragma solidity ^0.8.9;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Context variant with ERC2771 support.
*/
abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable _trustedForwarder;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address trustedForwarder) {
_trustedForwarder = trustedForwarder;
}
function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
return forwarder == _trustedForwarder;
}
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
/// @solidity memory-safe-assembly
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return super._msgSender();
}
}
function _msgData() internal view virtual override returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length - 20];
} else {
return super._msgData();
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.0;
import "./IERC1155Upgradeable.sol";
import "./IERC1155ReceiverUpgradeable.sol";
import "./extensions/IERC1155MetadataURIUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../utils/introspection/ERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
*
* _Available since v3.1._
*/
contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
using AddressUpgradeable for address;
// Mapping from token ID to account balances
mapping(uint256 => mapping(address => uint256)) private _balances;
// Mapping from account to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
string private _uri;
/**
* @dev See {_setURI}.
*/
function __ERC1155_init(string memory uri_) internal onlyInitializing {
__ERC1155_init_unchained(uri_);
}
function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
_setURI(uri_);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
return
interfaceId == type(IERC1155Upgradeable).interfaceId ||
interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC1155MetadataURI-uri}.
*
* This implementation returns the same URI for *all* token types. It relies
* on the token type ID substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/
function uri(uint256) public view virtual override returns (string memory) {
return _uri;
}
/**
* @dev See {IERC1155-balanceOf}.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: address zero is not a valid owner");
return _balances[id][account];
}
/**
* @dev See {IERC1155-balanceOfBatch}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
public
view
virtual
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner nor approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
emit TransferBatch(operator, from, to, ids, amounts);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
}
/**
* @dev Sets a new URI for all token types, by relying on the token type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* By this mechanism, any occurrence of the `\{id\}` substring in either the
* URI or any of the amounts in the JSON file at said URI will be replaced by
* clients with the token type ID.
*
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
* interpreted by clients as
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
* for token type ID 0x4cce0.
*
* See {uri}.
*
* Because these URIs cannot be meaningfully represented by the {URI} event,
* this function emits no events.
*/
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
/**
* @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
_balances[ids[i]][to] += amounts[i];
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
/**
* @dev Destroys `amount` tokens of token type `id` from `from`
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `amount` tokens of token type `id`.
*/
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
*/
function _burnBatch(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `ids` and `amounts` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `id` and `amount` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[47] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.0;
import "../IERC1155Upgradeable.sol";
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
*
* _Available since v3.1._
*/
interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {
/**
* @dev Returns the URI for token type `id`.
*
* If the `\{id\}` substring is present in the URI, it must be replaced by
* clients with the actual token type ID.
*/
function uri(uint256 id) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSAUpgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*
* @custom:storage-size 52
*/
abstract contract EIP712Upgradeable is Initializable {
/* solhint-disable var-name-mixedcase */
bytes32 private _HASHED_NAME;
bytes32 private _HASHED_VERSION;
bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
function __EIP712_init(string memory name, string memory version) internal onlyInitializing {
__EIP712_init_unchained(name, version);
}
function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev The hash of the name parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712NameHash() internal virtual view returns (bytes32) {
return _HASHED_NAME;
}
/**
* @dev The hash of the version parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712VersionHash() internal virtual view returns (bytes32) {
return _HASHED_VERSION;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../StringsUpgradeable.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.0;
import "./ERC1155Receiver.sol";
/**
* Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*
* @dev _Available since v3.1._
*/
contract ERC1155Holder is ERC1155Receiver {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../IERC1155Receiver.sol";
import "../../../utils/introspection/ERC165.sol";
/**
* @dev _Available since v3.1._
*/
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "../lib/CurrencyTransferLib.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract ERC20BulkSender is ReentrancyGuard, Ownable {
using SafeERC20 for IERC20;
uint256 public limit = 400;
event AirdropERC20(address indexed tokenAddress, address indexed tokenOwner, address indexed recipient, uint256 amount, bool success);
function setLimit(uint256 _limit) onlyOwner external {
limit = _limit;
}
function airdrop(address tokenAddress, address[] calldata recipients, uint256[] calldata amounts) external payable nonReentrant {
require(recipients.length == amounts.length, "ERC20BulkSender: Invalid input lengths");
require(recipients.length <= limit, "ERC20BulkSender: Too many recipients");
uint256 len = recipients.length;
uint256 totalAmount;
for (uint256 i = 0; i < amounts.length; i++) {
totalAmount += amounts[i];
}
if(tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
require(totalAmount == msg.value, "ERC20BulkSender: Incorrect native token amount");
}
else {
require(totalAmount <= IERC20(tokenAddress).allowance(msg.sender, address(this)), "ERC20BulkSender: Insufficient allowance");
}
uint256 refundAmount;
for (uint256 i = 0; i < len; i++) {
bool success = CurrencyTransferLib.transferCurrencyWithReturnVal(
tokenAddress,
msg.sender,
recipients[i],
amounts[i]
);
if (tokenAddress == CurrencyTransferLib.NATIVE_TOKEN && !success) {
refundAmount += amounts[i];
}
emit AirdropERC20(tokenAddress, msg.sender, recipients[i], amounts[i], success);
}
if (refundAmount > 0) {
// refund failed payments' amount to contract admin address
CurrencyTransferLib.safeTransferNativeToken(msg.sender, refundAmount);
}
}
receive() external payable {
// anonymous transfer: to admin
(bool success, ) = payable(owner()).call{value: msg.value}(
new bytes(0)
);
require(success, "ERC20BulkSender: Transfer failed");
}
fallback() external payable {
if (msg.value > 0) {
// call non exist function: send to admin
(bool success, ) = payable(owner()).call{value: msg.value}(new bytes(0));
require(success, "ERC20BulkSender: Transfer failed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "../lib/CurrencyTransferLib.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol";
contract ERC20QuestRewardsStorage {
/* ============ TypeHashes and Constants ============ */
bytes32 public constant ERC20_ACTIVATE_CAMPAIGN_TYPEHASH = keccak256(
"ERC20LaunchCampaign(uint96 cid,address admin,uint256 startTime,uint256 claimTime,CampaignReward[] campaignRewards)CampaignReward(uint96 rewardId,address tokenAddress,uint256 numRewards)"
);
bytes32 public constant ERC20_CLAIM_TYPEHASH = keccak256(
"ERC20Claim(uint96 rewardId,uint96 userId,address userAddress,uint256 amountToClaim)"
);
bytes32 public constant ERC20_DUMMY_CLAIM_TYPEHASH = keccak256(
"ERC20DummyClaim(uint96 cid,uint96 rewardId,uint96 userId,address userAddress)"
);
bytes32 public constant ERC20_REWARD_CONFIG_TYPEHASH = keccak256(
"CampaignReward(uint96 rewardId,address tokenAddress,uint256 numRewards)"
);
/* ============ Events ============ */
event ERC20SignerUpdate(address oldSigner, address newSigner);
event ERC20ClaimTimeUpdate(uint96 indexed cid, uint256 oldClaimTime, uint256 newClaimTime);
event ERC20LaunchCampaign(
uint96 indexed cid,
address admin,
uint256 startTime,
uint256 claimTime,
CampaignReward[] campaignRewards
);
event ERC20Claim(
uint96 indexed rewardId,
uint96 indexed userId,
address indexed userAddress,
uint256 amountToClaim
);
event ERC20DummyClaim(
uint96 indexed cid,
uint96 indexed rewardId,
uint96 indexed userId,
address userAddress
);
event ERC20Withdraw(
uint96 indexed cid,
uint96 indexed rewardId,
address indexed tokenAddress,
address admin,
uint256 amount
);
/* ============ Structs ============ */
// Input when activating a campaign
struct CampaignReward {
uint96 rewardId; // reward id
address tokenAddress; // token address
uint256 numRewards; // number of reward tokens
}
struct CampaignConfig {
address admin; // campaign admin, only admin can withdraw
uint256 startTime; // campaign start time
uint256 claimTime; // campaign claim time
}
struct RewardConfig {
uint96 cid; // campaign id
address tokenAddress; // token address
uint256 numRewards; // number of reward tokens
uint256 tokensClaimed; // number of tokens claimed
uint256 usersClaimed; // total number of addresses who claimed
}
/* ============ State Variables ============ */
// Intract Signer
address public intractSigner;
// cid => Campaign configuration
mapping(uint96 => CampaignConfig) public campaignConfigs;
// cid => array of rewardIds
// used only when admin wants to withdraw
mapping(uint96 => uint96[]) public campaignToRewards;
// rewardId => Reward configuration
mapping(uint96 => RewardConfig) public rewardConfigs;
// rewardId => userAddress => if he has claimed
mapping(uint96 => mapping(address => bool)) public hasClaimed;
// rewardId => userId => if he has claimed
mapping(uint96 => mapping(uint96 => bool)) public hasClaimedUserId;
// signature => if it has been used
mapping(bytes32 => bool) public usedDummyClaimHashes;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contract ERC20QuestRewards is Initializable, OwnableUpgradeable, PausableUpgradeable, EIP712Upgradeable, ReentrancyGuardUpgradeable, ERC2771ContextUpgradeable, ERC20QuestRewardsStorage {
using Address for address;
/* ============ Initial setup ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) ERC2771ContextUpgradeable(_trustedForwarder) {}
function initialize(address _intractSigner) external initializer {
require(_intractSigner != address(0), "ERC20QuestRewards: Intract signer address must not be null address");
__Ownable_init();
__Pausable_init();
__EIP712_init("IntractERC20QuestReward", "1.0.0");
__ReentrancyGuard_init();
intractSigner = _intractSigner;
emit ERC20SignerUpdate(address(0), _intractSigner);
}
/* ============ External Functions ============ */
function launchCampaign(
uint96 _cid,
uint256 _startTime,
uint256 _claimTime,
CampaignReward[] calldata _campaignRewards,
bytes calldata _signature
) external virtual payable whenNotPaused nonReentrant {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
require(
_startTime > 0 &&
_startTime < _claimTime &&
block.timestamp < _claimTime,
"ERC20QuestRewards: Invalid campaign time");
require(campaignConfigs[_cid].admin == address(0), "ERC20QuestRewards: Campaign has been activated");
uint256 nativeCoinsNeeded = 0;
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
require(numRewards > 0, "ERC20QuestRewards: Invalid number of reward tokens");
require(tokenAddress != address(0) && (tokenAddress.isContract() || tokenAddress == CurrencyTransferLib.NATIVE_TOKEN), "ERC20QuestRewards: Invalid token address");
if(tokenAddress == CurrencyTransferLib.NATIVE_TOKEN){
nativeCoinsNeeded += numRewards;
}
}
require(msg.value == nativeCoinsNeeded, "ERC20QuestRewards: Launch campaign fail, not enough coins");
require(
_verify(
_hashLaunchCampaign(_cid, _msgSender(), _startTime, _claimTime, _campaignRewards),
_signature
),
"ERC20QuestRewards: Invalid signature"
);
campaignConfigs[_cid] = CampaignConfig(
_msgSender(),
_startTime,
_claimTime
);
uint96[] memory rewardIdArr = new uint96[](_campaignRewards.length);
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
uint96 rewardId = _campaignRewards[i].rewardId;
if(tokenAddress != CurrencyTransferLib.NATIVE_TOKEN){
bool deposit = IERC20(tokenAddress).transferFrom(_msgSender(), address(this), numRewards);
require(deposit, "ERC20QuestRewards: Launch campaign fail, not enough tokens");
}
rewardConfigs[rewardId] = RewardConfig(
_cid,
tokenAddress,
numRewards,
0,
0
);
rewardIdArr[i] = _campaignRewards[i].rewardId;
}
campaignToRewards[_cid] = rewardIdArr;
emit ERC20LaunchCampaign(_cid, _msgSender(), _startTime, _claimTime, _campaignRewards);
}
function claim(
uint96 _rewardId,
uint96 _userId,
uint256 _amountToClaim,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_rewardId > 0, "ERC20QuestRewards: Invalid rewardId");
require(_userId > 0, "ERC20QuestRewards: Invalid userId");
require(_amountToClaim > 0, "ERC20QuestRewards: Invalid amount");
require(!hasClaimed[_rewardId][_msgSender()], "ERC20QuestRewards: Already claimed");
require(!hasClaimedUserId[_rewardId][_userId], "ERC20QuestRewards: Already claimed");
require(
_verify(
_hashClaim(_rewardId, _userId, _msgSender(), _amountToClaim),
_signature
),
"ERC20QuestRewards: Invalid signature"
);
RewardConfig storage rewardConfig = rewardConfigs[_rewardId];
CampaignConfig storage campaignConfig = campaignConfigs[rewardConfig.cid];
require(rewardConfig.tokensClaimed + _amountToClaim <= rewardConfig.numRewards, "ERC20QuestRewards: Insufficient rewards available");
require(campaignConfig.startTime < block.timestamp, "ERC20QuestRewards: Claim phase not started");
require(block.timestamp < campaignConfig.claimTime, "ERC20QuestRewards: Claim phase ended");
hasClaimed[_rewardId][_msgSender()] = true;
hasClaimedUserId[_rewardId][_userId] = true;
rewardConfig.tokensClaimed = rewardConfig.tokensClaimed + _amountToClaim;
rewardConfig.usersClaimed = rewardConfig.usersClaimed + 1;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
(bool success, ) = payable(_msgSender()).call{value: _amountToClaim}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(_msgSender(), _amountToClaim);
require(success, "ERC20QuestRewards: Transfer failed");
}
emit ERC20Claim(_rewardId, _userId, _msgSender(), _amountToClaim);
}
function dummyClaim(
uint96 _cid,
uint96 _rewardId,
uint96 _userId,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_userId > 0, "ERC20QuestRewards: Invalid userId");
bytes32 hash = _hashDummyClaim(_cid, _rewardId, _userId, _msgSender());
require(!usedDummyClaimHashes[hash], "ERC20QuestRewards: Already claimed");
require(
_verify(
hash,
_signature
),
"ERC20QuestRewards: Invalid signature"
);
uint96 dummyRewardId = 1;
uint256 _amountToClaim = 1;
RewardConfig storage rewardConfig = rewardConfigs[dummyRewardId];
require(rewardConfig.tokensClaimed + _amountToClaim <= rewardConfig.numRewards, "ERC20QuestRewards: Insufficient rewards available");
usedDummyClaimHashes[hash] = true;
rewardConfig.tokensClaimed = rewardConfig.tokensClaimed + _amountToClaim;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
(bool success, ) = payable(_msgSender()).call{value: _amountToClaim}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(_msgSender(), _amountToClaim);
require(success, "ERC20QuestRewards: Transfer failed");
}
emit ERC20DummyClaim(_cid, _rewardId, _userId, _msgSender());
}
function withdraw(uint96 _cid) external virtual whenNotPaused nonReentrant {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
CampaignConfig storage campaignConfig = campaignConfigs[_cid];
require(campaignConfig.admin != address(0), "ERC20QuestRewards: Campaign not found");
require(campaignConfig.startTime < block.timestamp, "ERC20QuestRewards: Withdraw phase not started");
require(campaignConfig.claimTime < block.timestamp, "ERC20QuestRewards: Claim phase still active");
uint96[] memory rewardIds = campaignToRewards[_cid];
uint256 nativeCoinsNeeded = 0;
for(uint256 i = 0; i < rewardIds.length; i++) {
RewardConfig storage rewardConfig = rewardConfigs[rewardIds[i]];
if(rewardConfig.tokensClaimed >= rewardConfig.numRewards) {
continue;
}
uint256 tokensLeft = rewardConfig.numRewards - rewardConfig.tokensClaimed;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
nativeCoinsNeeded = nativeCoinsNeeded + tokensLeft;
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(campaignConfig.admin, tokensLeft);
require(success, "ERC20QuestRewards: Transfer failed");
}
rewardConfig.tokensClaimed = rewardConfig.numRewards;
emit ERC20Withdraw(_cid, rewardIds[i], rewardConfig.tokenAddress, campaignConfig.admin, tokensLeft);
}
if(nativeCoinsNeeded > 0) {
(bool success, ) = campaignConfig.admin.call{value: nativeCoinsNeeded}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
}
}
/* ============ Owner Functions ============ */
function updateSigner(address _intractSigner) external onlyOwner {
require(_intractSigner != address(0), "ERC20QuestRewards: Invalid address");
intractSigner = _intractSigner;
emit ERC20SignerUpdate(intractSigner, _intractSigner);
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function updateClaimTime(uint96 _cid, uint256 _newClaimTime) external onlyOwner {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
CampaignConfig storage campaignConfig = campaignConfigs[_cid];
require(campaignConfig.admin != address(0), "ERC20QuestRewards: Campaign not found");
uint256 oldClaimTime = campaignConfig.claimTime;
campaignConfig.claimTime = _newClaimTime;
emit ERC20ClaimTimeUpdate(_cid, oldClaimTime, _newClaimTime);
}
/* ============ Fallback Functions ============ */
receive() external payable {
// anonymous transfer: to admin
(bool success, ) = payable(owner()).call{value: msg.value}(
new bytes(0)
);
require(success, "ERC20QuestRewards: Transfer failed");
}
fallback() external payable {
if (msg.value > 0) {
// call non exist function: send to admin
(bool success, ) = payable(owner()).call{value: msg.value}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
}
}
/* ============ Internal Functions ============ */
function _hashLaunchCampaign(
uint96 _cid,
address _admin,
uint256 _startTime,
uint256 _claimTime,
CampaignReward[] calldata _campaignRewards
) internal view returns (bytes32) {
bytes32[] memory encodedCamapignRewards = new bytes32[](_campaignRewards.length);
for(uint256 i = 0; i < _campaignRewards.length; i++) {
encodedCamapignRewards[i] = keccak256(
abi.encode(
ERC20_REWARD_CONFIG_TYPEHASH,
_campaignRewards[i].rewardId,
_campaignRewards[i].tokenAddress,
_campaignRewards[i].numRewards
)
);
}
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_ACTIVATE_CAMPAIGN_TYPEHASH,
_cid,
_admin,
_startTime,
_claimTime,
keccak256(abi.encodePacked(encodedCamapignRewards))
)
)
);
}
function _hashClaim(
uint96 _rewardId,
uint96 _userId,
address _userAddress,
uint256 _amountToClaim
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_CLAIM_TYPEHASH,
_rewardId,
_userId,
_userAddress,
_amountToClaim
)
)
);
}
function _hashDummyClaim(
uint96 _cid,
uint96 _rewardId,
uint96 _userId,
address _userAddress
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_DUMMY_CLAIM_TYPEHASH,
_cid,
_rewardId,
_userId,
_userAddress
)
)
);
}
function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
function _verify(bytes32 hash, bytes calldata signature) internal view returns (bool) {
return ECDSA.recover(hash, signature) == intractSigner;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 amount) external;
function transfer(address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
/// @author thirdweb
// Helper interfaces
import { IWETH } from "../interfaces/IWETH.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
library CurrencyTransferLib {
using SafeERC20 for IERC20;
/// @dev The address interpreted as native token of the chain.
address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Transfers a given amount of currency.
function transferCurrency(
address _currency,
address _from,
address _to,
uint256 _amount
) internal {
if (_amount == 0) {
return;
}
if (_currency == NATIVE_TOKEN) {
safeTransferNativeToken(_to, _amount);
} else {
safeTransferERC20(_currency, _from, _to, _amount);
}
}
/// @dev Transfers a given amount of currency. (With native token wrapping)
function transferCurrencyWithWrapper(
address _currency,
address _from,
address _to,
uint256 _amount,
address _nativeTokenWrapper
) internal {
if (_amount == 0) {
return;
}
if (_currency == NATIVE_TOKEN) {
if (_from == address(this)) {
// withdraw from weth then transfer withdrawn native token to recipient
IWETH(_nativeTokenWrapper).withdraw(_amount);
safeTransferNativeTokenWithWrapper(_to, _amount, _nativeTokenWrapper);
} else if (_to == address(this)) {
// store native currency in weth
require(_amount == msg.value, "msg.value != amount");
IWETH(_nativeTokenWrapper).deposit{ value: _amount }();
} else {
safeTransferNativeTokenWithWrapper(_to, _amount, _nativeTokenWrapper);
}
} else {
safeTransferERC20(_currency, _from, _to, _amount);
}
}
/// @dev Transfer `amount` of ERC20 token from `from` to `to`.
function safeTransferERC20(
address _currency,
address _from,
address _to,
uint256 _amount
) internal {
if (_from == _to) {
return;
}
if (_from == address(this)) {
IERC20(_currency).safeTransfer(_to, _amount);
} else {
IERC20(_currency).safeTransferFrom(_from, _to, _amount);
}
}
/// @dev Transfers `amount` of native token to `to`.
function safeTransferNativeToken(address to, uint256 value) internal {
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(bool success, ) = to.call{ value: value }("");
require(success, "native token transfer failed");
}
/// @dev Transfers `amount` of native token to `to`. (With native token wrapping)
function safeTransferNativeTokenWithWrapper(
address to,
uint256 value,
address _nativeTokenWrapper
) internal {
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(bool success, ) = to.call{ value: value }("");
if (!success) {
IWETH(_nativeTokenWrapper).deposit{ value: value }();
IERC20(_nativeTokenWrapper).safeTransfer(to, value);
}
}
/// @dev Transfers ERC20 tokens and returns a boolean i.e. the status of the transfer.
function transferCurrencyWithReturnVal(
address _currency,
address _from,
address _to,
uint256 _amount
) internal returns (bool success) {
if (_amount == 0) {
success = true;
return success;
}
if (_currency == CurrencyTransferLib.NATIVE_TOKEN) {
// solhint-disable avoid-low-level-calls
// slither-disable-next-line low-level-calls
(success, ) = _to.call{ value: _amount, gas: 80_000 }("");
} else {
(bool success_, bytes memory data_) = _currency.call(
abi.encodeWithSelector(IERC20.transferFrom.selector, _from, _to, _amount)
);
success = success_;
if (!success || (data_.length > 0 && !abi.decode(data_, (bool)))) {
success = false;
require(
IERC20(_currency).balanceOf(_from) >= _amount &&
IERC20(_currency).allowance(_from, address(this)) >= _amount,
"Not balance or allowance"
);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract BadAddress {
receive() external payable {
revert("Cannot accept ether");
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "../erc20/ERC20BulkSender.sol";
contract BadAddress2 {
address[] recipients = [address(this)];
uint256[] amounts = [0];
receive() external payable {
ERC20BulkSender(payable(msg.sender)).airdrop(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, recipients, amounts);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract BadAddress3 {
// no receive or fallback function
function hello() public returns (bool) {
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "../erc20/ERC20QuestRewards.sol";
import "hardhat/console.sol";
contract BadAddress4 {
uint96 rewardId;
uint96 userId;
uint256 amountToClaim;
bytes signature;
function storeParams(uint96 _rewardId, uint96 _userId, uint256 _amountToClaim, bytes memory _signature) public {
rewardId = _rewardId;
userId = _userId;
amountToClaim = _amountToClaim;
signature = _signature;
}
receive() external payable {
console.log("BadAddress4: msg.sender: %s", msg.sender);
try ERC20QuestRewards(payable(msg.sender)).claim(rewardId, userId, amountToClaim, signature) {
} catch Error(string memory reason) {
// catch failing revert() and require()
console.log("BadAddress4: Error: %s", reason);
} catch (bytes memory reason) {
// catch failing assert()
console.logBytes(reason);
}
}
function attack(address payable _target) public payable {
ERC20QuestRewards(_target).claim(rewardId, userId, amountToClaim, signature);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "../erc1155/Intractopia.sol";
import "hardhat/console.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
contract BadAddress5 is ERC1155Holder {
uint96 rewardId;
uint96 userId;
uint256 tokenId;
uint256 amountToClaim;
bytes signature;
function storeParams(uint96 _rewardId, uint96 _userId, uint256 _tokenId, uint256 _amountToClaim, bytes memory _signature) public {
rewardId = _rewardId;
userId = _userId;
tokenId = _tokenId;
amountToClaim = _amountToClaim;
signature = _signature;
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
console.log("BadAddress5: msg.sender: %s", msg.sender);
try Intractopia(payable(msg.sender)).claim(rewardId, userId, tokenId, amountToClaim, address(this), signature) {
} catch Error(string memory reason) {
// catch failing revert() and require()
console.log("BadAddress5: Error: %s", reason);
} catch (bytes memory reason) {
// catch failing assert()
console.logBytes(reason);
}
return this.onERC1155Received.selector;
}
function attack(address payable _target) public payable {
Intractopia(_target).claim(rewardId, userId, tokenId, amountToClaim, address(this), signature);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BadToken is ERC20 {
address bulkSender;
constructor(address _bulkSender) ERC20("Bad Token", "BT") {
bulkSender = _bulkSender;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {
if(msg.sender == bulkSender) {
revert("Bad Token");
}
}
function allowance(address owner, address spender) public view override returns (uint256) {
return 10000 ether;
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "../lib/CurrencyTransferLib.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol";
contract ERC20QuestRewardsStorage {
/* ============ TypeHashes and Constants ============ */
bytes32 public constant ERC20_ACTIVATE_CAMPAIGN_TYPEHASH = keccak256(
"ERC20LaunchCampaign(uint96 cid,address admin,uint256 startTime,uint256 claimTime,CampaignReward[] campaignRewards)CampaignReward(uint96 rewardId,address tokenAddress,uint256 numRewards)"
);
bytes32 public constant ERC20_CLAIM_TYPEHASH = keccak256(
"ERC20Claim(uint96 rewardId,uint96 userId,address userAddress,uint256 amountToClaim)"
);
bytes32 public constant ERC20_DUMMY_CLAIM_TYPEHASH = keccak256(
"ERC20DummyClaim(uint96 cid,uint96 rewardId,uint96 userId,address userAddress)"
);
bytes32 public constant ERC20_REWARD_CONFIG_TYPEHASH = keccak256(
"CampaignReward(uint96 rewardId,address tokenAddress,uint256 numRewards)"
);
/* ============ Events ============ */
event ERC20SignerUpdate(address oldSigner, address newSigner);
event ERC20ClaimTimeUpdate(uint96 indexed cid, uint256 oldClaimTime, uint256 newClaimTime);
event ERC20LaunchCampaign(
uint96 indexed cid,
address admin,
uint256 startTime,
uint256 claimTime,
CampaignReward[] campaignRewards
);
event ERC20Claim(
uint96 indexed rewardId,
uint96 indexed userId,
address indexed userAddress,
uint256 amountToClaim
);
event ERC20DummyClaim(
uint96 indexed cid,
uint96 indexed rewardId,
uint96 indexed userId,
address userAddress
);
event ERC20Withdraw(
uint96 indexed cid,
uint96 indexed rewardId,
address indexed tokenAddress,
address admin,
uint256 amount
);
/* ============ Structs ============ */
// Input when activating a campaign
struct CampaignReward {
uint96 rewardId; // reward id
address tokenAddress; // token address
uint256 numRewards; // number of reward tokens
}
struct CampaignConfig {
address admin; // campaign admin, only admin can withdraw
uint256 startTime; // campaign start time
uint256 claimTime; // campaign claim time
}
struct RewardConfig {
uint96 cid; // campaign id
address tokenAddress; // token address
uint256 numRewards; // number of reward tokens
uint256 tokensClaimed; // number of tokens claimed
uint256 usersClaimed; // total number of addresses who claimed
}
/* ============ State Variables ============ */
// Intract Signer
address public intractSigner;
// cid => Campaign configuration
mapping(uint96 => CampaignConfig) public campaignConfigs;
// cid => array of rewardIds
// used only when admin wants to withdraw
mapping(uint96 => uint96[]) public campaignToRewards;
// rewardId => Reward configuration
mapping(uint96 => RewardConfig) public rewardConfigs;
// rewardId => userAddress => if he has claimed
mapping(uint96 => mapping(address => bool)) public hasClaimed;
// rewardId => userId => if he has claimed
mapping(uint96 => mapping(uint96 => bool)) public hasClaimedUserId;
// signature => if it has been used
mapping(bytes32 => bool) public usedDummyClaimHashes;
uint256 public newVariable;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[48] private __gap;
}
contract ERC20QuestRewards_ is Initializable, OwnableUpgradeable, PausableUpgradeable, EIP712Upgradeable, ReentrancyGuardUpgradeable, ERC2771ContextUpgradeable, ERC20QuestRewardsStorage {
using Address for address;
/* ============ Initial setup ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) ERC2771ContextUpgradeable(_trustedForwarder) {}
function initialize(address _intractSigner) external initializer {
require(_intractSigner != address(0), "ERC20QuestRewards: Intract signer address must not be null address");
__Ownable_init();
__Pausable_init();
__EIP712_init("IntractERC20QuestReward", "1.0.0");
__ReentrancyGuard_init();
intractSigner = _intractSigner;
emit ERC20SignerUpdate(address(0), _intractSigner);
}
/* ============ External Functions ============ */
function launchCampaign(
uint96 _cid,
uint256 _startTime,
uint256 _claimTime,
CampaignReward[] calldata _campaignRewards,
bytes calldata _signature
) external virtual payable whenNotPaused nonReentrant {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
require(
_startTime > 0 &&
_startTime < _claimTime &&
block.timestamp < _claimTime,
"ERC20QuestRewards: Invalid campaign time");
require(campaignConfigs[_cid].admin == address(0), "ERC20QuestRewards: Campaign has been activated");
uint256 nativeCoinsNeeded = 0;
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
require(numRewards > 0, "ERC20QuestRewards: Invalid number of reward tokens");
require(tokenAddress != address(0) && (tokenAddress.isContract() || tokenAddress == CurrencyTransferLib.NATIVE_TOKEN), "ERC20QuestRewards: Invalid token address");
if(tokenAddress == CurrencyTransferLib.NATIVE_TOKEN){
nativeCoinsNeeded += numRewards;
}
}
require(msg.value == nativeCoinsNeeded, "ERC20QuestRewards: Launch campaign fail, not enough coins");
require(
_verify(
_hashLaunchCampaign(_cid, _msgSender(), _startTime, _claimTime, _campaignRewards),
_signature
),
"ERC20QuestRewards: Invalid signature"
);
campaignConfigs[_cid] = CampaignConfig(
_msgSender(),
_startTime,
_claimTime
);
uint96[] memory rewardIdArr = new uint96[](_campaignRewards.length);
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
uint96 rewardId = _campaignRewards[i].rewardId;
if(tokenAddress != CurrencyTransferLib.NATIVE_TOKEN){
bool deposit = IERC20(tokenAddress).transferFrom(_msgSender(), address(this), numRewards);
require(deposit, "ERC20QuestRewards: Launch campaign fail, not enough tokens");
}
rewardConfigs[rewardId] = RewardConfig(
_cid,
tokenAddress,
numRewards,
0,
0
);
rewardIdArr[i] = _campaignRewards[i].rewardId;
}
campaignToRewards[_cid] = rewardIdArr;
emit ERC20LaunchCampaign(_cid, _msgSender(), _startTime, _claimTime, _campaignRewards);
}
function claim(
uint96 _rewardId,
uint96 _userId,
uint256 _amountToClaim,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_rewardId > 0, "ERC20QuestRewards: Invalid rewardId");
require(_userId > 0, "ERC20QuestRewards: Invalid userId");
require(_amountToClaim > 0, "ERC20QuestRewards: Invalid amount");
require(!hasClaimed[_rewardId][_msgSender()], "ERC20QuestRewards: Already claimed");
require(!hasClaimedUserId[_rewardId][_userId], "ERC20QuestRewards: Already claimed");
require(
_verify(
_hashClaim(_rewardId, _userId, _msgSender(), _amountToClaim),
_signature
),
"ERC20QuestRewards: Invalid signature"
);
RewardConfig storage rewardConfig = rewardConfigs[_rewardId];
CampaignConfig storage campaignConfig = campaignConfigs[rewardConfig.cid];
require(rewardConfig.tokensClaimed + _amountToClaim <= rewardConfig.numRewards, "ERC20QuestRewards: Insufficient rewards available");
require(campaignConfig.startTime < block.timestamp, "ERC20QuestRewards: Claim phase not started");
require(block.timestamp < campaignConfig.claimTime, "ERC20QuestRewards: Claim phase ended");
hasClaimed[_rewardId][_msgSender()] = true;
hasClaimedUserId[_rewardId][_userId] = true;
rewardConfig.tokensClaimed = rewardConfig.tokensClaimed + _amountToClaim;
rewardConfig.usersClaimed = rewardConfig.usersClaimed + 1;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
(bool success, ) = payable(_msgSender()).call{value: _amountToClaim}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(_msgSender(), _amountToClaim);
require(success, "ERC20QuestRewards: Transfer failed");
}
emit ERC20Claim(_rewardId, _userId, _msgSender(), _amountToClaim);
}
function dummyClaim(
uint96 _cid,
uint96 _rewardId,
uint96 _userId,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_userId > 0, "ERC20QuestRewards: Invalid userId");
bytes32 hash = _hashDummyClaim(_cid, _rewardId, _userId, _msgSender());
require(!usedDummyClaimHashes[hash], "ERC20QuestRewards: Already claimed");
require(
_verify(
hash,
_signature
),
"ERC20QuestRewards: Invalid signature"
);
uint96 dummyRewardId = 1;
uint256 _amountToClaim = 1;
RewardConfig storage rewardConfig = rewardConfigs[dummyRewardId];
require(rewardConfig.tokensClaimed + _amountToClaim <= rewardConfig.numRewards, "ERC20QuestRewards: Insufficient rewards available");
usedDummyClaimHashes[hash] = true;
rewardConfig.tokensClaimed = rewardConfig.tokensClaimed + _amountToClaim;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
(bool success, ) = payable(_msgSender()).call{value: _amountToClaim}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(_msgSender(), _amountToClaim);
require(success, "ERC20QuestRewards: Transfer failed");
}
emit ERC20DummyClaim(_cid, _rewardId, _userId, _msgSender());
}
function withdraw(uint96 _cid) external virtual whenNotPaused nonReentrant {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
CampaignConfig storage campaignConfig = campaignConfigs[_cid];
require(campaignConfig.admin != address(0), "ERC20QuestRewards: Campaign not found");
require(campaignConfig.startTime < block.timestamp, "ERC20QuestRewards: Withdraw phase not started");
require(campaignConfig.claimTime < block.timestamp, "ERC20QuestRewards: Claim phase still active");
uint96[] memory rewardIds = campaignToRewards[_cid];
uint256 nativeCoinsNeeded = 0;
for(uint256 i = 0; i < rewardIds.length; i++) {
RewardConfig storage rewardConfig = rewardConfigs[rewardIds[i]];
if(rewardConfig.tokensClaimed >= rewardConfig.numRewards) {
continue;
}
uint256 tokensLeft = rewardConfig.numRewards - rewardConfig.tokensClaimed;
if (rewardConfig.tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
nativeCoinsNeeded = nativeCoinsNeeded + tokensLeft;
} else {
bool success = IERC20(rewardConfig.tokenAddress).transfer(campaignConfig.admin, tokensLeft);
require(success, "ERC20QuestRewards: Transfer failed");
}
rewardConfig.tokensClaimed = rewardConfig.numRewards;
emit ERC20Withdraw(_cid, rewardIds[i], rewardConfig.tokenAddress, campaignConfig.admin, tokensLeft);
}
if(nativeCoinsNeeded > 0) {
(bool success, ) = campaignConfig.admin.call{value: nativeCoinsNeeded}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
}
}
/* ============ Owner Functions ============ */
function updateSigner(address _intractSigner) external onlyOwner {
require(_intractSigner != address(0), "ERC20QuestRewards: Invalid address");
intractSigner = _intractSigner;
emit ERC20SignerUpdate(intractSigner, _intractSigner);
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function updateClaimTime(uint96 _cid, uint256 _newClaimTime) external onlyOwner {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
CampaignConfig storage campaignConfig = campaignConfigs[_cid];
require(campaignConfig.admin != address(0), "ERC20QuestRewards: Campaign not found");
uint256 oldClaimTime = campaignConfig.claimTime;
campaignConfig.claimTime = _newClaimTime;
emit ERC20ClaimTimeUpdate(_cid, oldClaimTime, _newClaimTime);
}
/* ============ Fallback Functions ============ */
receive() external payable {
// anonymous transfer: to admin
(bool success, ) = payable(owner()).call{value: msg.value}(
new bytes(0)
);
require(success, "ERC20QuestRewards: Transfer failed");
}
fallback() external payable {
if (msg.value > 0) {
// call non exist function: send to admin
(bool success, ) = payable(owner()).call{value: msg.value}(new bytes(0));
require(success, "ERC20QuestRewards: Transfer failed");
}
}
/* ============ Internal Functions ============ */
function _hashLaunchCampaign(
uint96 _cid,
address _admin,
uint256 _startTime,
uint256 _claimTime,
CampaignReward[] calldata _campaignRewards
) internal view returns (bytes32) {
bytes32[] memory encodedCamapignRewards = new bytes32[](_campaignRewards.length);
for(uint256 i = 0; i < _campaignRewards.length; i++) {
encodedCamapignRewards[i] = keccak256(
abi.encode(
ERC20_REWARD_CONFIG_TYPEHASH,
_campaignRewards[i].rewardId,
_campaignRewards[i].tokenAddress,
_campaignRewards[i].numRewards
)
);
}
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_ACTIVATE_CAMPAIGN_TYPEHASH,
_cid,
_admin,
_startTime,
_claimTime,
keccak256(abi.encodePacked(encodedCamapignRewards))
)
)
);
}
function _hashClaim(
uint96 _rewardId,
uint96 _userId,
address _userAddress,
uint256 _amountToClaim
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_CLAIM_TYPEHASH,
_rewardId,
_userId,
_userAddress,
_amountToClaim
)
)
);
}
function _hashDummyClaim(
uint96 _cid,
uint96 _rewardId,
uint96 _userId,
address _userAddress
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC20_DUMMY_CLAIM_TYPEHASH,
_cid,
_rewardId,
_userId,
_userAddress
)
)
);
}
function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
function _verify(bytes32 hash, bytes calldata signature) internal view returns (bool) {
return ECDSA.recover(hash, signature) == intractSigner;
}
}
contract ERC20QuestRewardsV2 is ERC20QuestRewards_ {
using Address for address;
/* ============ Constructor ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) ERC20QuestRewards_(_trustedForwarder) {}
/* ============ External Functions ============ */
function launchCampaign(
uint96 _cid,
uint256 _startTime,
uint256 _claimTime,
CampaignReward[] calldata _campaignRewards,
bytes calldata _signature
) external virtual override payable whenNotPaused nonReentrant {
require(_cid > 0, "ERC20QuestRewards: Invalid cid");
require(
_startTime > 0 &&
_startTime < _claimTime &&
block.timestamp < _claimTime,
"ERC20QuestRewards: Invalid campaign time");
require(campaignConfigs[_cid].admin == address(0), "ERC20QuestRewards: Campaign has been activated");
uint256 nativeCoinsNeeded = 0;
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
require(numRewards > 0, "ERC20QuestRewards: Invalid number of reward tokens");
require(tokenAddress != address(0) && (tokenAddress.isContract() || tokenAddress == CurrencyTransferLib.NATIVE_TOKEN), "ERC20QuestRewards: Invalid token address");
if(tokenAddress == CurrencyTransferLib.NATIVE_TOKEN){
nativeCoinsNeeded += numRewards;
}
}
require(msg.value == nativeCoinsNeeded, "ERC20QuestRewards: Launch campaign fail, not enough coins");
require(
_verify(
_hashLaunchCampaign(_cid, msg.sender, _startTime, _claimTime, _campaignRewards),
_signature
),
"ERC20QuestRewards: Invalid signature"
);
campaignConfigs[_cid] = CampaignConfig(
msg.sender,
_startTime,
_claimTime
);
uint96[] memory rewardIdArr = new uint96[](_campaignRewards.length);
for(uint256 i=0; i < _campaignRewards.length; i++) {
address tokenAddress = _campaignRewards[i].tokenAddress;
uint256 numRewards = _campaignRewards[i].numRewards;
uint96 rewardId = _campaignRewards[i].rewardId;
if(tokenAddress != CurrencyTransferLib.NATIVE_TOKEN){
bool deposit = IERC20(tokenAddress).transferFrom(msg.sender, address(this), numRewards);
require(deposit, "ERC20QuestRewards: Launch campaign fail, not enough tokens");
}
rewardConfigs[rewardId] = RewardConfig(
_cid,
tokenAddress,
numRewards,
0,
0
);
rewardIdArr[i] = _campaignRewards[i].rewardId;
}
campaignToRewards[_cid] = rewardIdArr;
emit ERC20LaunchCampaign(_cid, msg.sender, _startTime, _claimTime, _campaignRewards);
}
function version2() external pure returns (bool success) {
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract DummyToken is ERC20 {
uint256 public constant INITIAL_SUPPLY = type(uint256).max;
constructor() ERC20("Intract Dummy Token", "IDT") {
_mint(msg.sender, INITIAL_SUPPLY);
}
function decimals() public pure override returns (uint8) {
return 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import "hardhat/console.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
contract IntractopiaStorageV2 {
/* ============ TypeHashes and Constants ============ */
bytes32 public constant ERC1155_CLAIM_TYPEHASH = keccak256(
"ERC1155Claim(uint96 rewardId,uint96 userId,uint256 tokenId,address userAddress,uint256 amountToClaim)"
);
bytes32 public constant ERC1155_DUMMY_CLAIM_TYPEHASH = keccak256(
"ERC1155DummyClaim(uint96 rewardId,uint96 userId,address userAddress)"
);
/* ============ Events ============ */
event ERC1155SignerUpdate(address oldSigner, address newSigner);
event ERC1155AdminAdded(uint256 tokenId, address admin);
event ERC1155CollectionLaunch(
uint256 indexed tokenId,
address indexed creator,
uint256 initialSupply
);
event ERC1155Claim(
uint96 rewardId,
uint96 indexed userId,
uint256 indexed tokenId,
address indexed userAddress,
uint256 amountToClaim
);
event ERC1155DummyClaim(
uint96 indexed rewardId,
uint96 indexed userId,
address userAddress
);
/* ============ Structs ============ */
/* ============ State Variables ============ */
// Intract Signer
address public intractSigner;
// TokenId
uint256 public currentTokenId;
// Mapping from tokenId to creator address
mapping (uint256 => address) public creator;
// Mapping from tokenId to admin addresses
mapping (uint256 => mapping (address => bool)) public isAdmin;
// Mapping from tokenId to current token supply
mapping (uint256 => uint256) public tokenSupply;
// rewardId => userAddress => if he has claimed
mapping(uint96 => mapping(address => bool)) public hasClaimed;
// rewardId => userId => if he has claimed
mapping(uint96 => mapping(uint96 => bool)) public hasClaimedUserId;
// signature => if it has been used
mapping(bytes32 => bool) public usedDummyClaimHashes;
mapping(uint256 => string) public uris;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[48] private __gap;
}
contract IntractopiaV1 is Initializable, OwnableUpgradeable, PausableUpgradeable, EIP712Upgradeable, ReentrancyGuardUpgradeable, ERC1155Upgradeable, ERC2771ContextUpgradeable, IntractopiaStorageV2 {
/* ============ Modifiers ============ */
modifier tokenExists(uint256 _tokenId) {
require(creator[_tokenId] != address(0), "Intractopia: TokenId does not exist");
_;
}
modifier onlyAdmin(uint256 _tokenId) {
require(isAdmin[_tokenId][_msgSender()], "Intractopia: Only admin can call this function");
_;
}
/* ============ Initial setup ============ */
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) ERC2771ContextUpgradeable(_trustedForwarder) {}
function initialize(address _intractSigner, string calldata _uri) external initializer {
require(_intractSigner != address(0), "Intractopia: Intract signer address must not be null address");
__Ownable_init();
__Pausable_init();
__EIP712_init("Intractopia", "1.0.0");
__ReentrancyGuard_init();
__ERC1155_init(_uri);
intractSigner = _intractSigner;
currentTokenId = 1;
uint256 _id = currentTokenId;
creator[_id] = _msgSender();
isAdmin[_id][_msgSender()] = true;
_mint(_msgSender(), _id, 1, "");
tokenSupply[_id] = 1;
emit ERC1155SignerUpdate(address(0), _intractSigner);
}
/* ============ External Functions ============ */
function createCollection(
uint256 _initialSupply
) external virtual whenNotPaused nonReentrant returns (uint256) {
currentTokenId += 1;
uint256 _id = currentTokenId;
creator[_id] = _msgSender();
isAdmin[_id][_msgSender()] = true;
_mint(_msgSender(), _id, _initialSupply, "");
tokenSupply[_id] = _initialSupply;
emit ERC1155CollectionLaunch(_id, _msgSender(), _initialSupply);
return _id;
}
function claim(
uint96 _rewardId,
uint96 _userId,
uint256 _tokenId,
uint256 _amountToClaim,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant tokenExists(_tokenId) {
require(_rewardId > 0, "Intractopia: Invalid rewardId");
require(_userId > 0, "Intractopia: Invalid userId");
require(_tokenId > 0, "Intractopia: Invalid tokenId");
require(_amountToClaim > 0, "Intractopia: Invalid amount");
require(!hasClaimed[_rewardId][_msgSender()], "Intractopia: Already claimed");
require(!hasClaimedUserId[_rewardId][_userId], "Intractopia: Already claimed");
require(_verify(
_hashClaim(_rewardId, _userId, _tokenId, _msgSender(), _amountToClaim),
_signature
), "Intractopia: Invalid signature");
hasClaimed[_rewardId][_msgSender()] = true;
hasClaimedUserId[_rewardId][_userId] = true;
emit ERC1155Claim(_rewardId, _userId, _tokenId, _msgSender(), _amountToClaim);
_mint(_msgSender(), _tokenId, _amountToClaim, "");
}
function dummyClaim(
uint96 _rewardId,
uint96 _userId,
bytes calldata _signature
) external virtual whenNotPaused nonReentrant {
require(_rewardId > 0, "Intractopia: Invalid rewardId");
require(_userId > 0, "Intractopia: Invalid userId");
bytes32 hash = _hashDummyClaim(_rewardId, _userId, _msgSender());
require(!usedDummyClaimHashes[hash], "Intractopia: Already claimed");
uint256 amountToClaim = 1;
uint256 tokenId = 1;
require(_verify(
hash,
_signature
), "Intractopia: Invalid signature");
usedDummyClaimHashes[hash] = true;
emit ERC1155DummyClaim(_rewardId, _userId, _msgSender());
_mint(_msgSender(), tokenId, amountToClaim, "");
}
function uri(uint256 _tokenId) public virtual override view returns (string memory) {
return string(abi.encodePacked(super.uri(_tokenId), StringsUpgradeable.toString(_tokenId), ".json"));
}
/* ============ Owner Functions ============ */
function updateSigner(address _intractSigner) external onlyOwner {
require(_intractSigner != address(0), "Intractopia: Invalid address");
emit ERC1155SignerUpdate(intractSigner, _intractSigner);
intractSigner = _intractSigner;
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function setURI(string memory _uri) public onlyOwner {
_setURI(_uri);
}
/* ============ Token Admin Functions ============ */
function mint(
address _to,
uint256 _tokenId,
uint256 _amount,
bytes memory _data
) external virtual nonReentrant onlyAdmin(_tokenId) {
tokenSupply[_tokenId] += _amount;
super._mint(_to, _tokenId, _amount, _data);
}
function mintBatch(
address _to,
uint256[] memory _tokenIds,
uint256[] memory _amounts,
bytes memory _data
) external virtual nonReentrant {
for (uint256 i = 0; i < _tokenIds.length; i++) {
uint256 id = _tokenIds[i];
require(isAdmin[id][_msgSender()], "Intractopia: Only admin can call this function");
tokenSupply[id] += _amounts[i];
}
super._mintBatch(_to, _tokenIds, _amounts, _data);
}
function addAdmin(uint256 _tokenId, address _admin) external virtual onlyAdmin(_tokenId) {
require(_admin != address(0), "Intractopia: Invalid address");
isAdmin[_tokenId][_admin] = true;
emit ERC1155AdminAdded(_tokenId, _admin);
}
/* ============ Fallback Functions ============ */
receive() external payable {
// anonymous transfer: to admin
(bool success, ) = payable(owner()).call{value: msg.value}(
new bytes(0)
);
require(success, "Intractopia: Transfer failed");
}
fallback() external payable {
if (msg.value > 0) {
// call non exist function: send to admin
(bool success, ) = payable(owner()).call{value: msg.value}(new bytes(0));
require(success, "Intractopia: Transfer failed");
}
}
/* ============ Internal Functions ============ */
function _hashClaim(
uint96 _rewardId,
uint96 _userId,
uint256 _tokenId,
address _userAddress,
uint256 _amountToClaim
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC1155_CLAIM_TYPEHASH,
_rewardId,
_userId,
_tokenId,
_userAddress,
_amountToClaim
)
)
);
}
function _hashDummyClaim(
uint96 _rewardId,
uint96 _userId,
address _userAddress
) internal view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
ERC1155_DUMMY_CLAIM_TYPEHASH,
_rewardId,
_userId,
_userAddress
)
)
);
}
function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
function _verify(bytes32 hash, bytes calldata signature) internal view returns (bool) {
return ECDSA.recover(hash, signature) == intractSigner;
}
}
contract IntractopiaV2 is IntractopiaV1 {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address _trustedForwarder) IntractopiaV1(_trustedForwarder) {}
function createCollection(
uint256 _initialSupply,
string memory _uri
) external virtual whenNotPaused nonReentrant returns (uint256) {
currentTokenId += 1;
uint256 _id = currentTokenId;
creator[_id] = _msgSender();
isAdmin[_id][_msgSender()] = true;
tokenSupply[_id] = _initialSupply;
uris[_id] = _uri;
emit ERC1155CollectionLaunch(_id, _msgSender(), _initialSupply);
_mint(_msgSender(), _id, _initialSupply, "");
return _id;
}
function uri(uint256 _tokenId) public virtual override view returns (string memory) {
string memory tokenURI = uris[_tokenId];
if(bytes(tokenURI).length > 0) {
return tokenURI;
}
return super.uri(_tokenId);
}
function setURI(uint256 _tokenId, string memory _uri) external virtual onlyAdmin(_tokenId) {
uris[_tokenId] = _uri;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract USDC is ERC20 {
constructor() ERC20("USD Coin", "USDC") {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
function bulkMint(address[] calldata to, uint256 amount) external {
for(uint256 i = 0; i < to.length; i++) {
_mint(to[i], amount);
}
}
// function decimals() public view virtual override returns (uint8) {
// return 6;
// }
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_trustedForwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"ERC1155AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"rewardId","type":"uint96"},{"indexed":true,"internalType":"uint96","name":"userId","type":"uint96"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountToClaim","type":"uint256"}],"name":"ERC1155Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialSupply","type":"uint256"}],"name":"ERC1155CollectionLaunch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint96","name":"rewardId","type":"uint96"},{"indexed":true,"internalType":"uint96","name":"userId","type":"uint96"},{"indexed":false,"internalType":"address","name":"userAddress","type":"address"}],"name":"ERC1155DummyClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"ERC1155SignerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"ERC1155_CLAIM_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC1155_DUMMY_CLAIM_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_admin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"_rewardId","type":"uint96"},{"internalType":"uint96","name":"_userId","type":"uint96"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amountToClaim","type":"uint256"},{"internalType":"address","name":"_userAddress","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_initialSupply","type":"uint256"}],"name":"createCollection","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"creator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"_rewardId","type":"uint96"},{"internalType":"uint96","name":"_userId","type":"uint96"},{"internalType":"address","name":"_userAddress","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"dummyClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"","type":"uint96"},{"internalType":"address","name":"","type":"address"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"","type":"uint96"},{"internalType":"uint96","name":"","type":"uint96"}],"name":"hasClaimedUserId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_intractSigner","type":"address"},{"internalType":"string","name":"_uri","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"intractSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_intractSigner","type":"address"}],"name":"updateSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedDummyClaimHashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a06040523480156200001157600080fd5b5060405162003e0138038062003e01833981016040819052620000349162000046565b6001600160a01b031660805262000078565b6000602082840312156200005957600080fd5b81516001600160a01b03811681146200007157600080fd5b9392505050565b608051613d666200009b600039600081816105b401526126c50152613d666000f3fe6080604052600436106101fb5760003560e01c806359d162571161010d578063a7ecd37e116100a0578063dbdc814b1161006f578063dbdc814b14610795578063e985e9c5146107b5578063f242432a146107ff578063f2fde38b1461081f578063f399e22e1461083f576102d8565b8063a7ecd37e146106e5578063d0011d9d14610705578063d6a4222f14610725578063d6ea844914610759576102d8565b80638456cb59116100dc5780638456cb59146106725780638da5cb5b1461068757806394de1eac146106a5578063a22cb465146106c5576102d8565b806359d16257146106055780635c975abb14610625578063715018a61461063d578063731133e914610652576102d8565b80631f7fdffa116101905780633f4ba83a1161015f5780633f4ba83a146105065780634e1273f41461051b578063510b515814610548578063572b6c051461059757806357d1aeb5146105e4576102d8565b80631f7fdffa1461045c5780632693ebf21461047c5780632eb2c2d6146104aa57806339e83bea146104ca576102d8565b806304fdaa9a116101cc57806304fdaa9a1461038e57806305570dbc146103bf5780630e89341c146103f3578063146a291114610420576102d8565b80629a9b7b146102f4578062fdd58e1461031e57806301ffc9a71461033e57806302fe53051461036e576102d8565b366102d85760006102146033546001600160a01b031690565b604080516000815260208101918290526001600160a01b039290921691349161023d9190612f80565b60006040518083038185875af1925050503d806000811461027a576040519150601f19603f3d011682016040523d82523d6000602084013e61027f565b606091505b50509050806102d55760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a205472616e73666572206661696c65640000000060448201526064015b60405180910390fd5b50005b34156102f25760006102146033546001600160a01b031690565b005b34801561030057600080fd5b5061030b6101945481565b6040519081526020015b60405180910390f35b34801561032a57600080fd5b5061030b610339366004612fb8565b61085f565b34801561034a57600080fd5b5061035e610359366004612ff8565b6108f3565b6040519015158152602001610315565b34801561037a57600080fd5b506102f26103893660046130a5565b610945565b34801561039a57600080fd5b5061035e6103a93660046130ed565b61019a6020526000908152604090205460ff1681565b3480156103cb57600080fd5b5061030b7f9175b75f2204c4d4a610b1bbe17e5fa79fce7fbac7711cdf85d769cc3848bf4b81565b3480156103ff57600080fd5b5061041361040e3660046130ed565b610959565b6040516103159190613132565b34801561042c57600080fd5b5061035e61043b366004613145565b61019660209081526000928352604080842090915290825290205460ff1681565b34801561046857600080fd5b506102f2610477366004613225565b610994565b34801561048857600080fd5b5061030b6104973660046130ed565b6101976020526000908152604090205481565b3480156104b657600080fd5b506102f26104c53660046132bd565b610aac565b3480156104d657600080fd5b5061035e6104e536600461337d565b61019860209081526000928352604080842090915290825290205460ff1681565b34801561051257600080fd5b506102f2610b0a565b34801561052757600080fd5b5061053b6105363660046133a7565b610b1c565b60405161031591906134ac565b34801561055457600080fd5b5061057f6105633660046130ed565b610195602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610315565b3480156105a357600080fd5b5061035e6105b23660046134bf565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156105f057600080fd5b506101935461057f906001600160a01b031681565b34801561061157600080fd5b506102f261062036600461351b565b610c45565b34801561063157600080fd5b5060655460ff1661035e565b34801561064957600080fd5b506102f2611074565b34801561065e57600080fd5b506102f261066d3660046135a3565b611086565b34801561067e57600080fd5b506102f261113d565b34801561069357600080fd5b506033546001600160a01b031661057f565b3480156106b157600080fd5b506102f26106c03660046135f7565b61114d565b3480156106d157600080fd5b506102f26106e036600461366c565b6113c4565b3480156106f157600080fd5b506102f26107003660046134bf565b6113da565b34801561071157600080fd5b5061030b6107203660046130ed565b6114a3565b34801561073157600080fd5b5061030b7f52fbdc3c74d741f91e89924e509efb37938f77dc0b874d0ae67a551cead3594881565b34801561076557600080fd5b5061035e6107743660046136a8565b61019960209081526000928352604080842090915290825290205460ff1681565b3480156107a157600080fd5b506102f26107b0366004613145565b6115f3565b3480156107c157600080fd5b5061035e6107d03660046136d2565b6001600160a01b0391821660009081526101306020908152604080832093909416825291909152205460ff1690565b34801561080b57600080fd5b506102f261081a3660046136ee565b611708565b34801561082b57600080fd5b506102f261083a3660046134bf565b61175f565b34801561084b57600080fd5b506102f261085a366004613752565b6117d5565b60006001600160a01b0383166108ca5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084016102cc565b50600090815261012f602090815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061092457506001600160e01b031982166303a24d0760e21b145b8061093f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b61094d611b11565b61095681611b8a565b50565b606061096482611b9e565b61096d83611c33565b60405160200161097e9291906137a4565b6040516020818303038152906040529050919050565b600260cb5414156109b75760405162461bcd60e51b81526004016102cc906137e3565b600260cb5560005b8351811015610a945760008482815181106109dc576109dc61381a565b6020026020010151905061019660008281526020019081526020016000206000610a04611d38565b6001600160a01b0316815260208101919091526040016000205460ff16610a3d5760405162461bcd60e51b81526004016102cc90613830565b838281518110610a4f57610a4f61381a565b602002602001015161019760008381526020019081526020016000206000828254610a7a9190613894565b90915550829150610a8c9050816138ac565b9150506109bf565b50610aa184848484611d47565b5050600160cb555050565b610ab4611d38565b6001600160a01b0316856001600160a01b03161480610ada5750610ada856107d0611d38565b610af65760405162461bcd60e51b81526004016102cc906138c7565b610b038585858585611e9f565b5050505050565b610b12611b11565b610b1a61204b565b565b60608151835114610b815760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016102cc565b600083516001600160401b03811115610b9c57610b9c612f3e565b604051908082528060200260200182016040528015610bc5578160200160208202803683370190505b50905060005b8451811015610c3d57610c10858281518110610be957610be961381a565b6020026020010151858381518110610c0357610c0361381a565b602002602001015161085f565b828281518110610c2257610c2261381a565b6020908102919091010152610c36816138ac565b9050610bcb565b509392505050565b610c4d6120a3565b600260cb541415610c705760405162461bcd60e51b81526004016102cc906137e3565b600260cb556000858152610195602052604090205485906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602360248201527f496e74726163746f7069613a20546f6b656e496420646f6573206e6f742065786044820152621a5cdd60ea1b60648201526084016102cc565b6000886001600160601b031611610d415760405162461bcd60e51b815260206004820152601d60248201527f496e74726163746f7069613a20496e76616c696420726577617264496400000060448201526064016102cc565b6000876001600160601b031611610d9a5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420757365724964000000000060448201526064016102cc565b60008611610dea5760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420746f6b656e49640000000060448201526064016102cc565b60008511610e3a5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420616d6f756e74000000000060448201526064016102cc565b6001600160a01b038416610e905760405162461bcd60e51b815260206004820181905260248201527f496e74726163746f7069613a20496e76616c696420757365724164647265737360448201526064016102cc565b6001600160601b0388166000908152610198602090815260408083206001600160a01b038816845290915290205460ff1615610ede5760405162461bcd60e51b81526004016102cc90613916565b6001600160601b03808916600090815261019960209081526040808320938b168352929052205460ff1615610f255760405162461bcd60e51b81526004016102cc90613916565b610f3c610f35898989888a6120e9565b848461217a565b610f885760405162461bcd60e51b815260206004820152601e60248201527f496e74726163746f7069613a20496e76616c6964207369676e6174757265000060448201526064016102cc565b6001600160601b038881166000818152610198602090815260408083206001600160a01b038a168085529083528184208054600160ff1991821681179092558686526101998552838620978f168087529785529483902080549095161790935580519384529083018990529092899290917f55e45c439d1ff736812684adff4f5fc86d8db4de1374de90664ec17e7256f81e910160405180910390a46000868152610197602052604081208054879290611043908490613894565b92505081905550611065848787604051806020016040528060008152506121dc565b5050600160cb55505050505050565b61107c611b11565b610b1a60006122c4565b600260cb5414156110a95760405162461bcd60e51b81526004016102cc906137e3565b600260cb5560008381526101966020526040812084916110c7611d38565b6001600160a01b0316815260208101919091526040016000205460ff166111005760405162461bcd60e51b81526004016102cc90613830565b600084815261019760205260408120805485929061111f908490613894565b909155506111319050858585856121dc565b5050600160cb55505050565b611145611b11565b610b1a612316565b6111556120a3565b600260cb5414156111785760405162461bcd60e51b81526004016102cc906137e3565b600260cb556001600160601b0385166111d35760405162461bcd60e51b815260206004820152601d60248201527f496e74726163746f7069613a20496e76616c696420726577617264496400000060448201526064016102cc565b6000846001600160601b03161161122c5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420757365724964000000000060448201526064016102cc565b6001600160a01b0383166112825760405162461bcd60e51b815260206004820181905260248201527f496e74726163746f7069613a20496e76616c696420757365724164647265737360448201526064016102cc565b600061128f868686612354565b600081815261019a602052604090205490915060ff16156112c25760405162461bcd60e51b81526004016102cc90613916565b6001806112d083868661217a565b61131c5760405162461bcd60e51b815260206004820152601e60248201527f496e74726163746f7069613a20496e76616c6964207369676e6174757265000060448201526064016102cc565b600083815261019a6020908152604091829020805460ff1916600117905590516001600160a01b03881681526001600160601b0389811692908b16917faeedc887444f636ae962ff374f6709df2b420facc3749d5d6771d6bc4cdede5f910160405180910390a360008181526101976020526040812080548492906113a2908490613894565b92505081905550611065868284604051806020016040528060008152506121dc565b6113d66113cf611d38565b83836123b6565b5050565b6113e2611b11565b6001600160a01b0381166114385760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420616464726573730000000060448201526064016102cc565b61019354604080516001600160a01b03928316815291831660208301527f1bed810d070629e3c7f5073d5853d510358186fea41ee6b91e4c82b2ea38ed8f910160405180910390a161019380546001600160a01b0319166001600160a01b0392909216919091179055565b60006114ad6120a3565b600260cb5414156114d05760405162461bcd60e51b81526004016102cc906137e3565b600260cb81905550600161019460008282546114ec9190613894565b9091555050610194546114fd611d38565b60008281526101956020908152604080832080546001600160a01b0319166001600160a01b0395909516949094179093556101969052908120600191611541611d38565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905561158b611574611d38565b8285604051806020016040528060008152506121dc565b6000818152610197602052604090208390556115a5611d38565b6001600160a01b0316817febc11c13ed108c34e998bbf2874a52096c4fc5fea255aa86153110397d91f04a856040516115e091815260200190565b60405180910390a3600160cb5592915050565b600082815261019660205260408120839161160c611d38565b6001600160a01b0316815260208101919091526040016000205460ff166116455760405162461bcd60e51b81526004016102cc90613830565b6001600160a01b03821661169b5760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420616464726573730000000060448201526064016102cc565b6000838152610196602090815260408083206001600160a01b03861680855290835292819020805460ff191660011790558051868152918201929092527f74420b31ccd8bcac6b8a084da7b9253abd2ab85dd708b8c514b976c6b65d0d45910160405180910390a1505050565b611710611d38565b6001600160a01b0316856001600160a01b031614806117365750611736856107d0611d38565b6117525760405162461bcd60e51b81526004016102cc906138c7565b610b038585858585612498565b611767611b11565b6001600160a01b0381166117cc5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102cc565b610956816122c4565b600054610100900460ff16158080156117f55750600054600160ff909116105b8061180f5750303b15801561180f575060005460ff166001145b6118725760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102cc565b6000805460ff191660011790558015611895576000805461ff0019166101001790555b6001600160a01b0384166119115760405162461bcd60e51b815260206004820152603c60248201527f496e74726163746f7069613a20496e7472616374207369676e6572206164647260448201527f657373206d757374206e6f74206265206e756c6c20616464726573730000000060648201526084016102cc565b6119196125d3565b611921612602565b61196b6040518060400160405280600b81526020016a496e74726163746f70696160a81b815250604051806040016040528060058152602001640312e302e360dc1b815250612631565b611973612662565b6119b283838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061269192505050565b61019380546001600160a01b0319166001600160a01b03861617905560016101948190556119de611d38565b60008281526101956020908152604080832080546001600160a01b0319166001600160a01b0395909516949094179093556101969052908120600191611a22611d38565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055611a6d611a55611d38565b826001604051806020016040528060008152506121dc565b6000818152610197602090815260408083206001905580519283526001600160a01b038816918301919091527f1bed810d070629e3c7f5073d5853d510358186fea41ee6b91e4c82b2ea38ed8f910160405180910390a1508015611b0b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b611b19611d38565b6001600160a01b0316611b346033546001600160a01b031690565b6001600160a01b031614610b1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102cc565b80516113d690610131906020840190612ea5565b60606101318054611bae9061394d565b80601f0160208091040260200160405190810160405280929190818152602001828054611bda9061394d565b8015611c275780601f10611bfc57610100808354040283529160200191611c27565b820191906000526020600020905b815481529060010190602001808311611c0a57829003601f168201915b50505050509050919050565b606081611c575750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611c815780611c6b816138ac565b9150611c7a9050600a8361399e565b9150611c5b565b6000816001600160401b03811115611c9b57611c9b612f3e565b6040519080825280601f01601f191660200182016040528015611cc5576020820181803683370190505b5090505b8415611d3057611cda6001836139b2565b9150611ce7600a866139c9565b611cf2906030613894565b60f81b818381518110611d0757611d0761381a565b60200101906001600160f81b031916908160001a905350611d29600a8661399e565b9450611cc9565b949350505050565b6000611d426126c1565b905090565b6001600160a01b038416611d6d5760405162461bcd60e51b81526004016102cc906139dd565b8151835114611d8e5760405162461bcd60e51b81526004016102cc90613a1e565b6000611d98611d38565b905060005b8451811015611e3757838181518110611db857611db861381a565b602002602001015161012f6000878481518110611dd757611dd761381a565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254611e1f9190613894565b90915550819050611e2f816138ac565b915050611d9d565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611e88929190613a66565b60405180910390a4610b0381600087878787612709565b8151835114611ec05760405162461bcd60e51b81526004016102cc90613a1e565b6001600160a01b038416611ee65760405162461bcd60e51b81526004016102cc90613a94565b6000611ef0611d38565b905060005b8451811015611fdd576000858281518110611f1257611f1261381a565b602002602001015190506000858381518110611f3057611f3061381a565b602090810291909101810151600084815261012f835260408082206001600160a01b038e168352909352919091205490915081811015611f825760405162461bcd60e51b81526004016102cc90613ad9565b600083815261012f602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611fc2908490613894565b9250508190555050505080611fd6906138ac565b9050611ef5565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161202d929190613a66565b60405180910390a4612043818787878787612709565b505050505050565b612053612874565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612086611d38565b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff1615610b1a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016102cc565b604080517f52fbdc3c74d741f91e89924e509efb37938f77dc0b874d0ae67a551cead3594860208201526001600160601b03808816928201929092529085166060820152608081018490526001600160a01b03831660a082015260c081018290526000906121709060e0015b604051602081830303815290604052805190602001206128bd565b9695505050505050565b61019354604080516020601f85018190048102820181019092528381526000926001600160a01b0316916121ca918791879087908190840183828082843760009201919091525061290b92505050565b6001600160a01b031614949350505050565b6001600160a01b0384166122025760405162461bcd60e51b81526004016102cc906139dd565b600061220c611d38565b9050600061221985612927565b9050600061222685612927565b9050600086815261012f602090815260408083206001600160a01b038b1684529091528120805487929061225b908490613894565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46122bb83600089898989612972565b50505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61231e6120a3565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612086611d38565b604080517f9175b75f2204c4d4a610b1bbe17e5fa79fce7fbac7711cdf85d769cc3848bf4b60208201526001600160601b038086169282019290925290831660608201526001600160a01b0382166080820152600090611d309060a001612155565b816001600160a01b0316836001600160a01b0316141561242a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016102cc565b6001600160a01b0383811660008181526101306020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0384166124be5760405162461bcd60e51b81526004016102cc90613a94565b60006124c8611d38565b905060006124d585612927565b905060006124e285612927565b9050600086815261012f602090815260408083206001600160a01b038c168452909152902054858110156125285760405162461bcd60e51b81526004016102cc90613ad9565b600087815261012f602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290612568908490613894565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46125c8848a8a8a8a8a612972565b505050505050505050565b600054610100900460ff166125fa5760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a3c565b600054610100900460ff166126295760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a73565b600054610100900460ff166126585760405162461bcd60e51b81526004016102cc90613b23565b6113d68282612aa6565b600054610100900460ff166126895760405162461bcd60e51b81526004016102cc90613b23565b610b1a612ae7565b600054610100900460ff166126b85760405162461bcd60e51b81526004016102cc90613b23565b61095681612b15565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331415612701575060131936013560601c90565b503390565b90565b6001600160a01b0384163b156120435760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061274d9089908990889088908890600401613b6e565b602060405180830381600087803b15801561276757600080fd5b505af1925050508015612797575060408051601f3d908101601f1916820190925261279491810190613bcc565b60015b612844576127a3613be9565b806308c379a014156127dd57506127b8613c04565b806127c357506127df565b8060405162461bcd60e51b81526004016102cc9190613132565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016102cc565b6001600160e01b0319811663bc197c8160e01b146122bb5760405162461bcd60e51b81526004016102cc90613c8d565b60655460ff16610b1a5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102cc565b600061093f6128ca612b3c565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080600061291a8585612bb7565b91509150610c3d81612bfd565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106129615761296161381a565b602090810291909101015292915050565b6001600160a01b0384163b156120435760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906129b69089908990889088908890600401613cd5565b602060405180830381600087803b1580156129d057600080fd5b505af1925050508015612a00575060408051601f3d908101601f191682019092526129fd91810190613bcc565b60015b612a0c576127a3613be9565b6001600160e01b0319811663f23a6e6160e01b146122bb5760405162461bcd60e51b81526004016102cc90613c8d565b600054610100900460ff16612a635760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a6e611d38565b6122c4565b600054610100900460ff16612a9a5760405162461bcd60e51b81526004016102cc90613b23565b6065805460ff19169055565b600054610100900460ff16612acd5760405162461bcd60e51b81526004016102cc90613b23565b815160209283012081519190920120609791909155609855565b600054610100900460ff16612b0e5760405162461bcd60e51b81526004016102cc90613b23565b600160cb55565b600054610100900460ff1661094d5760405162461bcd60e51b81526004016102cc90613b23565b6000611d427f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612b6b60975490565b6098546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600080825160411415612bee5760208301516040840151606085015160001a612be287828585612db8565b94509450505050612bf6565b506000905060025b9250929050565b6000816004811115612c1157612c11613d1a565b1415612c1a5750565b6001816004811115612c2e57612c2e613d1a565b1415612c7c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016102cc565b6002816004811115612c9057612c90613d1a565b1415612cde5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016102cc565b6003816004811115612cf257612cf2613d1a565b1415612d4b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016102cc565b6004816004811115612d5f57612d5f613d1a565b14156109565760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016102cc565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612def5750600090506003612e9c565b8460ff16601b14158015612e0757508460ff16601c14155b15612e185750600090506004612e9c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612e6c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e9557600060019250925050612e9c565b9150600090505b94509492505050565b828054612eb19061394d565b90600052602060002090601f016020900481019282612ed35760008555612f19565b82601f10612eec57805160ff1916838001178555612f19565b82800160010185558215612f19579182015b82811115612f19578251825591602001919060010190612efe565b50612f25929150612f29565b5090565b5b80821115612f255760008155600101612f2a565b634e487b7160e01b600052604160045260246000fd5b60005b83811015612f6f578181015183820152602001612f57565b83811115611b0b5750506000910152565b60008251612f92818460208701612f54565b9190910192915050565b80356001600160a01b0381168114612fb357600080fd5b919050565b60008060408385031215612fcb57600080fd5b612fd483612f9c565b946020939093013593505050565b6001600160e01b03198116811461095657600080fd5b60006020828403121561300a57600080fd5b813561301581612fe2565b9392505050565b601f8201601f191681016001600160401b038111828210171561304157613041612f3e565b6040525050565b60006001600160401b0383111561306157613061612f3e565b604051613078601f8501601f19166020018261301c565b80915083815284848401111561308d57600080fd5b83836020830137600060208583010152509392505050565b6000602082840312156130b757600080fd5b81356001600160401b038111156130cd57600080fd5b8201601f810184136130de57600080fd5b611d3084823560208401613048565b6000602082840312156130ff57600080fd5b5035919050565b6000815180845261311e816020860160208601612f54565b601f01601f19169290920160200192915050565b6020815260006130156020830184613106565b6000806040838503121561315857600080fd5b8235915061316860208401612f9c565b90509250929050565b60006001600160401b0382111561318a5761318a612f3e565b5060051b60200190565b600082601f8301126131a557600080fd5b813560206131b282613171565b6040516131bf828261301c565b83815260059390931b85018201928281019150868411156131df57600080fd5b8286015b848110156131fa57803583529183019183016131e3565b509695505050505050565b600082601f83011261321657600080fd5b61301583833560208501613048565b6000806000806080858703121561323b57600080fd5b61324485612f9c565b935060208501356001600160401b038082111561326057600080fd5b61326c88838901613194565b9450604087013591508082111561328257600080fd5b61328e88838901613194565b935060608701359150808211156132a457600080fd5b506132b187828801613205565b91505092959194509250565b600080600080600060a086880312156132d557600080fd5b6132de86612f9c565b94506132ec60208701612f9c565b935060408601356001600160401b038082111561330857600080fd5b61331489838a01613194565b9450606088013591508082111561332a57600080fd5b61333689838a01613194565b9350608088013591508082111561334c57600080fd5b5061335988828901613205565b9150509295509295909350565b80356001600160601b0381168114612fb357600080fd5b6000806040838503121561339057600080fd5b61339983613366565b915061316860208401612f9c565b600080604083850312156133ba57600080fd5b82356001600160401b03808211156133d157600080fd5b818501915085601f8301126133e557600080fd5b813560206133f282613171565b6040516133ff828261301c565b83815260059390931b850182019282810191508984111561341f57600080fd5b948201945b838610156134445761343586612f9c565b82529482019490820190613424565b9650508601359250508082111561345a57600080fd5b5061346785828601613194565b9150509250929050565b600081518084526020808501945080840160005b838110156134a157815187529582019590820190600101613485565b509495945050505050565b6020815260006130156020830184613471565b6000602082840312156134d157600080fd5b61301582612f9c565b60008083601f8401126134ec57600080fd5b5081356001600160401b0381111561350357600080fd5b602083019150836020828501011115612bf657600080fd5b600080600080600080600060c0888a03121561353657600080fd5b61353f88613366565b965061354d60208901613366565b9550604088013594506060880135935061356960808901612f9c565b925060a08801356001600160401b0381111561358457600080fd5b6135908a828b016134da565b989b979a50959850939692959293505050565b600080600080608085870312156135b957600080fd5b6135c285612f9c565b9350602085013592506040850135915060608501356001600160401b038111156135eb57600080fd5b6132b187828801613205565b60008060008060006080868803121561360f57600080fd5b61361886613366565b945061362660208701613366565b935061363460408701612f9c565b925060608601356001600160401b0381111561364f57600080fd5b61365b888289016134da565b969995985093965092949392505050565b6000806040838503121561367f57600080fd5b61368883612f9c565b91506020830135801515811461369d57600080fd5b809150509250929050565b600080604083850312156136bb57600080fd5b6136c483613366565b915061316860208401613366565b600080604083850312156136e557600080fd5b61339983612f9c565b600080600080600060a0868803121561370657600080fd5b61370f86612f9c565b945061371d60208701612f9c565b9350604086013592506060860135915060808601356001600160401b0381111561374657600080fd5b61335988828901613205565b60008060006040848603121561376757600080fd5b61377084612f9c565b925060208401356001600160401b0381111561378b57600080fd5b613797868287016134da565b9497909650939450505050565b600083516137b6818460208801612f54565b8351908301906137ca818360208801612f54565b64173539b7b760d91b9101908152600501949350505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f496e74726163746f7069613a204f6e6c792061646d696e2063616e2063616c6c60408201526d103a3434b990333ab731ba34b7b760911b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082198211156138a7576138a761387e565b500190565b60006000198214156138c0576138c061387e565b5060010190565b6020808252602f908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526e195c881b9bdc88185c1c1c9bdd9959608a1b606082015260800190565b6020808252601c908201527f496e74726163746f7069613a20416c726561647920636c61696d656400000000604082015260600190565b600181811c9082168061396157607f821691505b6020821081141561398257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601260045260246000fd5b6000826139ad576139ad613988565b500490565b6000828210156139c4576139c461387e565b500390565b6000826139d8576139d8613988565b500690565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b604081526000613a796040830185613471565b8281036020840152613a8b8185613471565b95945050505050565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b0386811682528516602082015260a060408201819052600090613b9a90830186613471565b8281036060840152613bac8186613471565b90508281036080840152613bc08185613106565b98975050505050505050565b600060208284031215613bde57600080fd5b815161301581612fe2565b600060033d11156127065760046000803e5060005160e01c90565b600060443d1015613c125790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715613c4157505050505090565b8285019150815181811115613c595750505050505090565b843d8701016020828501011115613c735750505050505090565b613c826020828601018761301c565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090613d0f90830184613106565b979650505050505050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220da2feff0257b5280c1fa25b0b334cebacd33e1db30d5b1a815a5de2a10c154a064736f6c63430008090033000000000000000000000000fe0fa3c06d03bdc7fb49c892bbb39113b534fb57
Deployed Bytecode
0x6080604052600436106101fb5760003560e01c806359d162571161010d578063a7ecd37e116100a0578063dbdc814b1161006f578063dbdc814b14610795578063e985e9c5146107b5578063f242432a146107ff578063f2fde38b1461081f578063f399e22e1461083f576102d8565b8063a7ecd37e146106e5578063d0011d9d14610705578063d6a4222f14610725578063d6ea844914610759576102d8565b80638456cb59116100dc5780638456cb59146106725780638da5cb5b1461068757806394de1eac146106a5578063a22cb465146106c5576102d8565b806359d16257146106055780635c975abb14610625578063715018a61461063d578063731133e914610652576102d8565b80631f7fdffa116101905780633f4ba83a1161015f5780633f4ba83a146105065780634e1273f41461051b578063510b515814610548578063572b6c051461059757806357d1aeb5146105e4576102d8565b80631f7fdffa1461045c5780632693ebf21461047c5780632eb2c2d6146104aa57806339e83bea146104ca576102d8565b806304fdaa9a116101cc57806304fdaa9a1461038e57806305570dbc146103bf5780630e89341c146103f3578063146a291114610420576102d8565b80629a9b7b146102f4578062fdd58e1461031e57806301ffc9a71461033e57806302fe53051461036e576102d8565b366102d85760006102146033546001600160a01b031690565b604080516000815260208101918290526001600160a01b039290921691349161023d9190612f80565b60006040518083038185875af1925050503d806000811461027a576040519150601f19603f3d011682016040523d82523d6000602084013e61027f565b606091505b50509050806102d55760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a205472616e73666572206661696c65640000000060448201526064015b60405180910390fd5b50005b34156102f25760006102146033546001600160a01b031690565b005b34801561030057600080fd5b5061030b6101945481565b6040519081526020015b60405180910390f35b34801561032a57600080fd5b5061030b610339366004612fb8565b61085f565b34801561034a57600080fd5b5061035e610359366004612ff8565b6108f3565b6040519015158152602001610315565b34801561037a57600080fd5b506102f26103893660046130a5565b610945565b34801561039a57600080fd5b5061035e6103a93660046130ed565b61019a6020526000908152604090205460ff1681565b3480156103cb57600080fd5b5061030b7f9175b75f2204c4d4a610b1bbe17e5fa79fce7fbac7711cdf85d769cc3848bf4b81565b3480156103ff57600080fd5b5061041361040e3660046130ed565b610959565b6040516103159190613132565b34801561042c57600080fd5b5061035e61043b366004613145565b61019660209081526000928352604080842090915290825290205460ff1681565b34801561046857600080fd5b506102f2610477366004613225565b610994565b34801561048857600080fd5b5061030b6104973660046130ed565b6101976020526000908152604090205481565b3480156104b657600080fd5b506102f26104c53660046132bd565b610aac565b3480156104d657600080fd5b5061035e6104e536600461337d565b61019860209081526000928352604080842090915290825290205460ff1681565b34801561051257600080fd5b506102f2610b0a565b34801561052757600080fd5b5061053b6105363660046133a7565b610b1c565b60405161031591906134ac565b34801561055457600080fd5b5061057f6105633660046130ed565b610195602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610315565b3480156105a357600080fd5b5061035e6105b23660046134bf565b7f000000000000000000000000fe0fa3c06d03bdc7fb49c892bbb39113b534fb576001600160a01b0390811691161490565b3480156105f057600080fd5b506101935461057f906001600160a01b031681565b34801561061157600080fd5b506102f261062036600461351b565b610c45565b34801561063157600080fd5b5060655460ff1661035e565b34801561064957600080fd5b506102f2611074565b34801561065e57600080fd5b506102f261066d3660046135a3565b611086565b34801561067e57600080fd5b506102f261113d565b34801561069357600080fd5b506033546001600160a01b031661057f565b3480156106b157600080fd5b506102f26106c03660046135f7565b61114d565b3480156106d157600080fd5b506102f26106e036600461366c565b6113c4565b3480156106f157600080fd5b506102f26107003660046134bf565b6113da565b34801561071157600080fd5b5061030b6107203660046130ed565b6114a3565b34801561073157600080fd5b5061030b7f52fbdc3c74d741f91e89924e509efb37938f77dc0b874d0ae67a551cead3594881565b34801561076557600080fd5b5061035e6107743660046136a8565b61019960209081526000928352604080842090915290825290205460ff1681565b3480156107a157600080fd5b506102f26107b0366004613145565b6115f3565b3480156107c157600080fd5b5061035e6107d03660046136d2565b6001600160a01b0391821660009081526101306020908152604080832093909416825291909152205460ff1690565b34801561080b57600080fd5b506102f261081a3660046136ee565b611708565b34801561082b57600080fd5b506102f261083a3660046134bf565b61175f565b34801561084b57600080fd5b506102f261085a366004613752565b6117d5565b60006001600160a01b0383166108ca5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084016102cc565b50600090815261012f602090815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061092457506001600160e01b031982166303a24d0760e21b145b8061093f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b61094d611b11565b61095681611b8a565b50565b606061096482611b9e565b61096d83611c33565b60405160200161097e9291906137a4565b6040516020818303038152906040529050919050565b600260cb5414156109b75760405162461bcd60e51b81526004016102cc906137e3565b600260cb5560005b8351811015610a945760008482815181106109dc576109dc61381a565b6020026020010151905061019660008281526020019081526020016000206000610a04611d38565b6001600160a01b0316815260208101919091526040016000205460ff16610a3d5760405162461bcd60e51b81526004016102cc90613830565b838281518110610a4f57610a4f61381a565b602002602001015161019760008381526020019081526020016000206000828254610a7a9190613894565b90915550829150610a8c9050816138ac565b9150506109bf565b50610aa184848484611d47565b5050600160cb555050565b610ab4611d38565b6001600160a01b0316856001600160a01b03161480610ada5750610ada856107d0611d38565b610af65760405162461bcd60e51b81526004016102cc906138c7565b610b038585858585611e9f565b5050505050565b610b12611b11565b610b1a61204b565b565b60608151835114610b815760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b60648201526084016102cc565b600083516001600160401b03811115610b9c57610b9c612f3e565b604051908082528060200260200182016040528015610bc5578160200160208202803683370190505b50905060005b8451811015610c3d57610c10858281518110610be957610be961381a565b6020026020010151858381518110610c0357610c0361381a565b602002602001015161085f565b828281518110610c2257610c2261381a565b6020908102919091010152610c36816138ac565b9050610bcb565b509392505050565b610c4d6120a3565b600260cb541415610c705760405162461bcd60e51b81526004016102cc906137e3565b600260cb556000858152610195602052604090205485906001600160a01b0316610ce85760405162461bcd60e51b815260206004820152602360248201527f496e74726163746f7069613a20546f6b656e496420646f6573206e6f742065786044820152621a5cdd60ea1b60648201526084016102cc565b6000886001600160601b031611610d415760405162461bcd60e51b815260206004820152601d60248201527f496e74726163746f7069613a20496e76616c696420726577617264496400000060448201526064016102cc565b6000876001600160601b031611610d9a5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420757365724964000000000060448201526064016102cc565b60008611610dea5760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420746f6b656e49640000000060448201526064016102cc565b60008511610e3a5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420616d6f756e74000000000060448201526064016102cc565b6001600160a01b038416610e905760405162461bcd60e51b815260206004820181905260248201527f496e74726163746f7069613a20496e76616c696420757365724164647265737360448201526064016102cc565b6001600160601b0388166000908152610198602090815260408083206001600160a01b038816845290915290205460ff1615610ede5760405162461bcd60e51b81526004016102cc90613916565b6001600160601b03808916600090815261019960209081526040808320938b168352929052205460ff1615610f255760405162461bcd60e51b81526004016102cc90613916565b610f3c610f35898989888a6120e9565b848461217a565b610f885760405162461bcd60e51b815260206004820152601e60248201527f496e74726163746f7069613a20496e76616c6964207369676e6174757265000060448201526064016102cc565b6001600160601b038881166000818152610198602090815260408083206001600160a01b038a168085529083528184208054600160ff1991821681179092558686526101998552838620978f168087529785529483902080549095161790935580519384529083018990529092899290917f55e45c439d1ff736812684adff4f5fc86d8db4de1374de90664ec17e7256f81e910160405180910390a46000868152610197602052604081208054879290611043908490613894565b92505081905550611065848787604051806020016040528060008152506121dc565b5050600160cb55505050505050565b61107c611b11565b610b1a60006122c4565b600260cb5414156110a95760405162461bcd60e51b81526004016102cc906137e3565b600260cb5560008381526101966020526040812084916110c7611d38565b6001600160a01b0316815260208101919091526040016000205460ff166111005760405162461bcd60e51b81526004016102cc90613830565b600084815261019760205260408120805485929061111f908490613894565b909155506111319050858585856121dc565b5050600160cb55505050565b611145611b11565b610b1a612316565b6111556120a3565b600260cb5414156111785760405162461bcd60e51b81526004016102cc906137e3565b600260cb556001600160601b0385166111d35760405162461bcd60e51b815260206004820152601d60248201527f496e74726163746f7069613a20496e76616c696420726577617264496400000060448201526064016102cc565b6000846001600160601b03161161122c5760405162461bcd60e51b815260206004820152601b60248201527f496e74726163746f7069613a20496e76616c696420757365724964000000000060448201526064016102cc565b6001600160a01b0383166112825760405162461bcd60e51b815260206004820181905260248201527f496e74726163746f7069613a20496e76616c696420757365724164647265737360448201526064016102cc565b600061128f868686612354565b600081815261019a602052604090205490915060ff16156112c25760405162461bcd60e51b81526004016102cc90613916565b6001806112d083868661217a565b61131c5760405162461bcd60e51b815260206004820152601e60248201527f496e74726163746f7069613a20496e76616c6964207369676e6174757265000060448201526064016102cc565b600083815261019a6020908152604091829020805460ff1916600117905590516001600160a01b03881681526001600160601b0389811692908b16917faeedc887444f636ae962ff374f6709df2b420facc3749d5d6771d6bc4cdede5f910160405180910390a360008181526101976020526040812080548492906113a2908490613894565b92505081905550611065868284604051806020016040528060008152506121dc565b6113d66113cf611d38565b83836123b6565b5050565b6113e2611b11565b6001600160a01b0381166114385760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420616464726573730000000060448201526064016102cc565b61019354604080516001600160a01b03928316815291831660208301527f1bed810d070629e3c7f5073d5853d510358186fea41ee6b91e4c82b2ea38ed8f910160405180910390a161019380546001600160a01b0319166001600160a01b0392909216919091179055565b60006114ad6120a3565b600260cb5414156114d05760405162461bcd60e51b81526004016102cc906137e3565b600260cb81905550600161019460008282546114ec9190613894565b9091555050610194546114fd611d38565b60008281526101956020908152604080832080546001600160a01b0319166001600160a01b0395909516949094179093556101969052908120600191611541611d38565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905561158b611574611d38565b8285604051806020016040528060008152506121dc565b6000818152610197602052604090208390556115a5611d38565b6001600160a01b0316817febc11c13ed108c34e998bbf2874a52096c4fc5fea255aa86153110397d91f04a856040516115e091815260200190565b60405180910390a3600160cb5592915050565b600082815261019660205260408120839161160c611d38565b6001600160a01b0316815260208101919091526040016000205460ff166116455760405162461bcd60e51b81526004016102cc90613830565b6001600160a01b03821661169b5760405162461bcd60e51b815260206004820152601c60248201527f496e74726163746f7069613a20496e76616c696420616464726573730000000060448201526064016102cc565b6000838152610196602090815260408083206001600160a01b03861680855290835292819020805460ff191660011790558051868152918201929092527f74420b31ccd8bcac6b8a084da7b9253abd2ab85dd708b8c514b976c6b65d0d45910160405180910390a1505050565b611710611d38565b6001600160a01b0316856001600160a01b031614806117365750611736856107d0611d38565b6117525760405162461bcd60e51b81526004016102cc906138c7565b610b038585858585612498565b611767611b11565b6001600160a01b0381166117cc5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102cc565b610956816122c4565b600054610100900460ff16158080156117f55750600054600160ff909116105b8061180f5750303b15801561180f575060005460ff166001145b6118725760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102cc565b6000805460ff191660011790558015611895576000805461ff0019166101001790555b6001600160a01b0384166119115760405162461bcd60e51b815260206004820152603c60248201527f496e74726163746f7069613a20496e7472616374207369676e6572206164647260448201527f657373206d757374206e6f74206265206e756c6c20616464726573730000000060648201526084016102cc565b6119196125d3565b611921612602565b61196b6040518060400160405280600b81526020016a496e74726163746f70696160a81b815250604051806040016040528060058152602001640312e302e360dc1b815250612631565b611973612662565b6119b283838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061269192505050565b61019380546001600160a01b0319166001600160a01b03861617905560016101948190556119de611d38565b60008281526101956020908152604080832080546001600160a01b0319166001600160a01b0395909516949094179093556101969052908120600191611a22611d38565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055611a6d611a55611d38565b826001604051806020016040528060008152506121dc565b6000818152610197602090815260408083206001905580519283526001600160a01b038816918301919091527f1bed810d070629e3c7f5073d5853d510358186fea41ee6b91e4c82b2ea38ed8f910160405180910390a1508015611b0b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b611b19611d38565b6001600160a01b0316611b346033546001600160a01b031690565b6001600160a01b031614610b1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102cc565b80516113d690610131906020840190612ea5565b60606101318054611bae9061394d565b80601f0160208091040260200160405190810160405280929190818152602001828054611bda9061394d565b8015611c275780601f10611bfc57610100808354040283529160200191611c27565b820191906000526020600020905b815481529060010190602001808311611c0a57829003601f168201915b50505050509050919050565b606081611c575750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611c815780611c6b816138ac565b9150611c7a9050600a8361399e565b9150611c5b565b6000816001600160401b03811115611c9b57611c9b612f3e565b6040519080825280601f01601f191660200182016040528015611cc5576020820181803683370190505b5090505b8415611d3057611cda6001836139b2565b9150611ce7600a866139c9565b611cf2906030613894565b60f81b818381518110611d0757611d0761381a565b60200101906001600160f81b031916908160001a905350611d29600a8661399e565b9450611cc9565b949350505050565b6000611d426126c1565b905090565b6001600160a01b038416611d6d5760405162461bcd60e51b81526004016102cc906139dd565b8151835114611d8e5760405162461bcd60e51b81526004016102cc90613a1e565b6000611d98611d38565b905060005b8451811015611e3757838181518110611db857611db861381a565b602002602001015161012f6000878481518110611dd757611dd761381a565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254611e1f9190613894565b90915550819050611e2f816138ac565b915050611d9d565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611e88929190613a66565b60405180910390a4610b0381600087878787612709565b8151835114611ec05760405162461bcd60e51b81526004016102cc90613a1e565b6001600160a01b038416611ee65760405162461bcd60e51b81526004016102cc90613a94565b6000611ef0611d38565b905060005b8451811015611fdd576000858281518110611f1257611f1261381a565b602002602001015190506000858381518110611f3057611f3061381a565b602090810291909101810151600084815261012f835260408082206001600160a01b038e168352909352919091205490915081811015611f825760405162461bcd60e51b81526004016102cc90613ad9565b600083815261012f602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611fc2908490613894565b9250508190555050505080611fd6906138ac565b9050611ef5565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161202d929190613a66565b60405180910390a4612043818787878787612709565b505050505050565b612053612874565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612086611d38565b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff1615610b1a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016102cc565b604080517f52fbdc3c74d741f91e89924e509efb37938f77dc0b874d0ae67a551cead3594860208201526001600160601b03808816928201929092529085166060820152608081018490526001600160a01b03831660a082015260c081018290526000906121709060e0015b604051602081830303815290604052805190602001206128bd565b9695505050505050565b61019354604080516020601f85018190048102820181019092528381526000926001600160a01b0316916121ca918791879087908190840183828082843760009201919091525061290b92505050565b6001600160a01b031614949350505050565b6001600160a01b0384166122025760405162461bcd60e51b81526004016102cc906139dd565b600061220c611d38565b9050600061221985612927565b9050600061222685612927565b9050600086815261012f602090815260408083206001600160a01b038b1684529091528120805487929061225b908490613894565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46122bb83600089898989612972565b50505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61231e6120a3565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612086611d38565b604080517f9175b75f2204c4d4a610b1bbe17e5fa79fce7fbac7711cdf85d769cc3848bf4b60208201526001600160601b038086169282019290925290831660608201526001600160a01b0382166080820152600090611d309060a001612155565b816001600160a01b0316836001600160a01b0316141561242a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b60648201526084016102cc565b6001600160a01b0383811660008181526101306020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0384166124be5760405162461bcd60e51b81526004016102cc90613a94565b60006124c8611d38565b905060006124d585612927565b905060006124e285612927565b9050600086815261012f602090815260408083206001600160a01b038c168452909152902054858110156125285760405162461bcd60e51b81526004016102cc90613ad9565b600087815261012f602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290612568908490613894565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46125c8848a8a8a8a8a612972565b505050505050505050565b600054610100900460ff166125fa5760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a3c565b600054610100900460ff166126295760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a73565b600054610100900460ff166126585760405162461bcd60e51b81526004016102cc90613b23565b6113d68282612aa6565b600054610100900460ff166126895760405162461bcd60e51b81526004016102cc90613b23565b610b1a612ae7565b600054610100900460ff166126b85760405162461bcd60e51b81526004016102cc90613b23565b61095681612b15565b60007f000000000000000000000000fe0fa3c06d03bdc7fb49c892bbb39113b534fb576001600160a01b0316331415612701575060131936013560601c90565b503390565b90565b6001600160a01b0384163b156120435760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061274d9089908990889088908890600401613b6e565b602060405180830381600087803b15801561276757600080fd5b505af1925050508015612797575060408051601f3d908101601f1916820190925261279491810190613bcc565b60015b612844576127a3613be9565b806308c379a014156127dd57506127b8613c04565b806127c357506127df565b8060405162461bcd60e51b81526004016102cc9190613132565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e20455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b60648201526084016102cc565b6001600160e01b0319811663bc197c8160e01b146122bb5760405162461bcd60e51b81526004016102cc90613c8d565b60655460ff16610b1a5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102cc565b600061093f6128ca612b3c565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080600061291a8585612bb7565b91509150610c3d81612bfd565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106129615761296161381a565b602090810291909101015292915050565b6001600160a01b0384163b156120435760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906129b69089908990889088908890600401613cd5565b602060405180830381600087803b1580156129d057600080fd5b505af1925050508015612a00575060408051601f3d908101601f191682019092526129fd91810190613bcc565b60015b612a0c576127a3613be9565b6001600160e01b0319811663f23a6e6160e01b146122bb5760405162461bcd60e51b81526004016102cc90613c8d565b600054610100900460ff16612a635760405162461bcd60e51b81526004016102cc90613b23565b610b1a612a6e611d38565b6122c4565b600054610100900460ff16612a9a5760405162461bcd60e51b81526004016102cc90613b23565b6065805460ff19169055565b600054610100900460ff16612acd5760405162461bcd60e51b81526004016102cc90613b23565b815160209283012081519190920120609791909155609855565b600054610100900460ff16612b0e5760405162461bcd60e51b81526004016102cc90613b23565b600160cb55565b600054610100900460ff1661094d5760405162461bcd60e51b81526004016102cc90613b23565b6000611d427f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612b6b60975490565b6098546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600080825160411415612bee5760208301516040840151606085015160001a612be287828585612db8565b94509450505050612bf6565b506000905060025b9250929050565b6000816004811115612c1157612c11613d1a565b1415612c1a5750565b6001816004811115612c2e57612c2e613d1a565b1415612c7c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016102cc565b6002816004811115612c9057612c90613d1a565b1415612cde5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016102cc565b6003816004811115612cf257612cf2613d1a565b1415612d4b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016102cc565b6004816004811115612d5f57612d5f613d1a565b14156109565760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016102cc565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612def5750600090506003612e9c565b8460ff16601b14158015612e0757508460ff16601c14155b15612e185750600090506004612e9c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612e6c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e9557600060019250925050612e9c565b9150600090505b94509492505050565b828054612eb19061394d565b90600052602060002090601f016020900481019282612ed35760008555612f19565b82601f10612eec57805160ff1916838001178555612f19565b82800160010185558215612f19579182015b82811115612f19578251825591602001919060010190612efe565b50612f25929150612f29565b5090565b5b80821115612f255760008155600101612f2a565b634e487b7160e01b600052604160045260246000fd5b60005b83811015612f6f578181015183820152602001612f57565b83811115611b0b5750506000910152565b60008251612f92818460208701612f54565b9190910192915050565b80356001600160a01b0381168114612fb357600080fd5b919050565b60008060408385031215612fcb57600080fd5b612fd483612f9c565b946020939093013593505050565b6001600160e01b03198116811461095657600080fd5b60006020828403121561300a57600080fd5b813561301581612fe2565b9392505050565b601f8201601f191681016001600160401b038111828210171561304157613041612f3e565b6040525050565b60006001600160401b0383111561306157613061612f3e565b604051613078601f8501601f19166020018261301c565b80915083815284848401111561308d57600080fd5b83836020830137600060208583010152509392505050565b6000602082840312156130b757600080fd5b81356001600160401b038111156130cd57600080fd5b8201601f810184136130de57600080fd5b611d3084823560208401613048565b6000602082840312156130ff57600080fd5b5035919050565b6000815180845261311e816020860160208601612f54565b601f01601f19169290920160200192915050565b6020815260006130156020830184613106565b6000806040838503121561315857600080fd5b8235915061316860208401612f9c565b90509250929050565b60006001600160401b0382111561318a5761318a612f3e565b5060051b60200190565b600082601f8301126131a557600080fd5b813560206131b282613171565b6040516131bf828261301c565b83815260059390931b85018201928281019150868411156131df57600080fd5b8286015b848110156131fa57803583529183019183016131e3565b509695505050505050565b600082601f83011261321657600080fd5b61301583833560208501613048565b6000806000806080858703121561323b57600080fd5b61324485612f9c565b935060208501356001600160401b038082111561326057600080fd5b61326c88838901613194565b9450604087013591508082111561328257600080fd5b61328e88838901613194565b935060608701359150808211156132a457600080fd5b506132b187828801613205565b91505092959194509250565b600080600080600060a086880312156132d557600080fd5b6132de86612f9c565b94506132ec60208701612f9c565b935060408601356001600160401b038082111561330857600080fd5b61331489838a01613194565b9450606088013591508082111561332a57600080fd5b61333689838a01613194565b9350608088013591508082111561334c57600080fd5b5061335988828901613205565b9150509295509295909350565b80356001600160601b0381168114612fb357600080fd5b6000806040838503121561339057600080fd5b61339983613366565b915061316860208401612f9c565b600080604083850312156133ba57600080fd5b82356001600160401b03808211156133d157600080fd5b818501915085601f8301126133e557600080fd5b813560206133f282613171565b6040516133ff828261301c565b83815260059390931b850182019282810191508984111561341f57600080fd5b948201945b838610156134445761343586612f9c565b82529482019490820190613424565b9650508601359250508082111561345a57600080fd5b5061346785828601613194565b9150509250929050565b600081518084526020808501945080840160005b838110156134a157815187529582019590820190600101613485565b509495945050505050565b6020815260006130156020830184613471565b6000602082840312156134d157600080fd5b61301582612f9c565b60008083601f8401126134ec57600080fd5b5081356001600160401b0381111561350357600080fd5b602083019150836020828501011115612bf657600080fd5b600080600080600080600060c0888a03121561353657600080fd5b61353f88613366565b965061354d60208901613366565b9550604088013594506060880135935061356960808901612f9c565b925060a08801356001600160401b0381111561358457600080fd5b6135908a828b016134da565b989b979a50959850939692959293505050565b600080600080608085870312156135b957600080fd5b6135c285612f9c565b9350602085013592506040850135915060608501356001600160401b038111156135eb57600080fd5b6132b187828801613205565b60008060008060006080868803121561360f57600080fd5b61361886613366565b945061362660208701613366565b935061363460408701612f9c565b925060608601356001600160401b0381111561364f57600080fd5b61365b888289016134da565b969995985093965092949392505050565b6000806040838503121561367f57600080fd5b61368883612f9c565b91506020830135801515811461369d57600080fd5b809150509250929050565b600080604083850312156136bb57600080fd5b6136c483613366565b915061316860208401613366565b600080604083850312156136e557600080fd5b61339983612f9c565b600080600080600060a0868803121561370657600080fd5b61370f86612f9c565b945061371d60208701612f9c565b9350604086013592506060860135915060808601356001600160401b0381111561374657600080fd5b61335988828901613205565b60008060006040848603121561376757600080fd5b61377084612f9c565b925060208401356001600160401b0381111561378b57600080fd5b613797868287016134da565b9497909650939450505050565b600083516137b6818460208801612f54565b8351908301906137ca818360208801612f54565b64173539b7b760d91b9101908152600501949350505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f496e74726163746f7069613a204f6e6c792061646d696e2063616e2063616c6c60408201526d103a3434b990333ab731ba34b7b760911b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082198211156138a7576138a761387e565b500190565b60006000198214156138c0576138c061387e565b5060010190565b6020808252602f908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526e195c881b9bdc88185c1c1c9bdd9959608a1b606082015260800190565b6020808252601c908201527f496e74726163746f7069613a20416c726561647920636c61696d656400000000604082015260600190565b600181811c9082168061396157607f821691505b6020821081141561398257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601260045260246000fd5b6000826139ad576139ad613988565b500490565b6000828210156139c4576139c461387e565b500390565b6000826139d8576139d8613988565b500690565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b604081526000613a796040830185613471565b8281036020840152613a8b8185613471565b95945050505050565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b0386811682528516602082015260a060408201819052600090613b9a90830186613471565b8281036060840152613bac8186613471565b90508281036080840152613bc08185613106565b98975050505050505050565b600060208284031215613bde57600080fd5b815161301581612fe2565b600060033d11156127065760046000803e5060005160e01c90565b600060443d1015613c125790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715613c4157505050505090565b8285019150815181811115613c595750505050505090565b843d8701016020828501011115613c735750505050505090565b613c826020828601018761301c565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090613d0f90830184613106565b979650505050505050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220da2feff0257b5280c1fa25b0b334cebacd33e1db30d5b1a815a5de2a10c154a064736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fe0fa3c06d03bdc7fb49c892bbb39113b534fb57
-----Decoded View---------------
Arg [0] : _trustedForwarder (address): 0xfe0fa3C06d03bDC7fb49c892BbB39113B534fB57
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000fe0fa3c06d03bdc7fb49c892bbb39113b534fb57
Deployed Bytecode Sourcemap
2915:8257:32:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9060:12;9086:7;1513:6:0;;-1:-1:-1;;;;;1513:6:0;;1441:85;9086:7:32;9131:12;;;9141:1;9131:12;;;;;;;;;-1:-1:-1;;;;;9078:21:32;;;;;9107:9;;9078:75;;9131:12;9078:75;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9059:94;;;9171:7;9163:48;;;;-1:-1:-1;;;9163:48:32;;890:2:48;9163:48:32;;;872:21:48;929:2;909:18;;;902:30;968;948:18;;;941:58;1016:18;;9163:48:32;;;;;;;;;9009:209;2915:8257;;9266:9;:13;9262:232;;9350:12;9376:7;1513:6:0;;-1:-1:-1;;;;;1513:6:0;;1441:85;9262:232:32;2915:8257;1939:29;;;;;;;;;;;;;;;;;;;1191:25:48;;;1179:2;1164:18;1939:29:32;;;;;;;;2593:227:5;;;;;;;;;;-1:-1:-1;2593:227:5;;;;;:::i;:::-;;:::i;1600:349::-;;;;;;;;;;-1:-1:-1;1600:349:5;;;;;:::i;:::-;;:::i;:::-;;;2215:14:48;;2208:22;2190:41;;2178:2;2163:18;1600:349:5;2050:187:48;7741:83:32;;;;;;;;;;-1:-1:-1;7741:83:32;;;;;:::i;:::-;;:::i;2567:52::-;;;;;;;;;;-1:-1:-1;2567:52:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;976:150;;;;;;;;;;;;1031:95;976:150;;7085:201;;;;;;;;;;-1:-1:-1;7085:201:32;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2116:61::-;;;;;;;;;;-1:-1:-1;2116:61:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;8166:489;;;;;;;;;;-1:-1:-1;8166:489:32;;;;;:::i;:::-;;:::i;2233:47::-;;;;;;;;;;-1:-1:-1;2233:47:32;;;;;:::i;:::-;;;;;;;;;;;;;;4473:427:5;;;;;;;;;;-1:-1:-1;4473:427:5;;;;;:::i;:::-;;:::i;2339:61:32:-;;;;;;;;;;-1:-1:-1;2339:61:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;7672:63;;;;;;;;;;;;;:::i;2977:508:5:-;;;;;;;;;;-1:-1:-1;2977:508:5;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2019:43:32:-;;;;;;;;;;-1:-1:-1;2019:43:32;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;2019:43:32;;;;;;-1:-1:-1;;;;;10219:32:48;;;10201:51;;10189:2;10174:18;2019:43:32;10055:203:48;627:136:1;;;;;;;;;;-1:-1:-1;627:136:1;;;;;:::i;:::-;739:17;-1:-1:-1;;;;;726:30:1;;;;;;;627:136;1888:28:32;;;;;;;;;;-1:-1:-1;1888:28:32;;;;-1:-1:-1;;;;;1888:28:32;;;4850:1270;;;;;;;;;;-1:-1:-1;4850:1270:32;;;;;:::i;:::-;;:::i;1858:84:3:-;;;;;;;;;;-1:-1:-1;1928:7:3;;;;1858:84;;2071:101:0;;;;;;;;;;;;;:::i;7889:271:32:-;;;;;;;;;;-1:-1:-1;7889:271:32;;;;;:::i;:::-;;:::i;7607:59::-;;;;;;;;;;;;;:::i;1441:85:0:-;;;;;;;;;;-1:-1:-1;1513:6:0;;-1:-1:-1;;;;;1513:6:0;1441:85;;6126:953:32;;;;;;;;;;-1:-1:-1;6126:953:32;;;;;:::i;:::-;;:::i;3553:153:5:-;;;;;;;;;;-1:-1:-1;3553:153:5;;;;;:::i;:::-;;:::i;7345:256:32:-;;;;;;;;;;-1:-1:-1;7345:256:32;;;;;:::i;:::-;;:::i;4410:434::-;;;;;;;;;;-1:-1:-1;4410:434:32;;;;;:::i;:::-;;:::i;792:177::-;;;;;;;;;;;;841:128;792:177;;2454:66;;;;;;;;;;-1:-1:-1;2454:66:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;8661:259;;;;;;;;;;-1:-1:-1;8661:259:32;;;;;:::i;:::-;;:::i;3773:166:5:-;;;;;;;;;;-1:-1:-1;3773:166:5;;;;;:::i;:::-;-1:-1:-1;;;;;3895:27:5;;;3872:4;3895:27;;;:18;:27;;;;;;;;:37;;;;;;;;;;;;;;;3773:166;4006:395;;;;;;;;;;-1:-1:-1;4006:395:5;;;;;:::i;:::-;;:::i;2321:198:0:-;;;;;;;;;;-1:-1:-1;2321:198:0;;;;;:::i;:::-;;:::i;3671:680:32:-;;;;;;;;;;-1:-1:-1;3671:680:32;;;;;:::i;:::-;;:::i;2593:227:5:-;2679:7;-1:-1:-1;;;;;2706:21:5;;2698:76;;;;-1:-1:-1;;;2698:76:5;;14926:2:48;2698:76:5;;;14908:21:48;14965:2;14945:18;;;14938:30;15004:34;14984:18;;;14977:62;-1:-1:-1;;;15055:18:48;;;15048:40;15105:19;;2698:76:5;14724:406:48;2698:76:5;-1:-1:-1;2791:13:5;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;2791:22:5;;;;;;;;;;;;2593:227::o;1600:349::-;1724:4;-1:-1:-1;;;;;;1759:52:5;;-1:-1:-1;;;1759:52:5;;:131;;-1:-1:-1;;;;;;;1827:63:5;;-1:-1:-1;;;1827:63:5;1759:131;:183;;;-1:-1:-1;;;;;;;;;;1168:51:14;;;1906:36:5;1740:202;1600:349;-1:-1:-1;;1600:349:5:o;7741:83:32:-;1334:13:0;:11;:13::i;:::-;7804::32::1;7812:4;7804:7;:13::i;:::-;7741:83:::0;:::o;7085:201::-;7154:13;7210:19;7220:8;7210:9;:19::i;:::-;7231:37;7259:8;7231:27;:37::i;:::-;7193:85;;;;;;;;;:::i;:::-;;;;;;;;;;;;;7179:100;;7085:201;;;:::o;8166:489::-;1815:1:4;2569:7;;:19;;2561:63;;;;-1:-1:-1;;;2561:63:4;;;;;;;:::i;:::-;1815:1;2699:7;:18;8356:9:32::1;8351:239;8375:9;:16;8371:1;:20;8351:239;;;8412:10;8425:9;8435:1;8425:12;;;;;;;;:::i;:::-;;;;;;;8412:25;;8459:7;:11;8467:2;8459:11;;;;;;;;;;;:25;8471:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;8459:25:32::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;8459:25:32;;::::1;;8451:84;;;;-1:-1:-1::0;;;8451:84:32::1;;;;;;;:::i;:::-;8568:8;8577:1;8568:11;;;;;;;;:::i;:::-;;;;;;;8549;:15;8561:2;8549:15;;;;;;;;;;;;:30;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;8393:3:32;;-1:-1:-1;8393:3:32::1;::::0;-1:-1:-1;8393:3:32;::::1;:::i;:::-;;;;8351:239;;;;8599:49;8616:3;8621:9;8632:8;8642:5;8599:16;:49::i;:::-;-1:-1:-1::0;;1772:1:4;2872:7;:22;-1:-1:-1;;8166:489:32:o;4473:427:5:-;4706:12;:10;:12::i;:::-;-1:-1:-1;;;;;4698:20:5;:4;-1:-1:-1;;;;;4698:20:5;;:60;;;;4722:36;4739:4;4745:12;:10;:12::i;4722:36::-;4677:154;;;;-1:-1:-1;;;4677:154:5;;;;;;;:::i;:::-;4841:52;4864:4;4870:2;4874:3;4879:7;4888:4;4841:22;:52::i;:::-;4473:427;;;;;:::o;7672:63:32:-;1334:13:0;:11;:13::i;:::-;7718:10:32::1;:8;:10::i;:::-;7672:63::o:0;2977:508:5:-;3128:16;3187:3;:10;3168:8;:15;:29;3160:83;;;;-1:-1:-1;;;3160:83:5;;17707:2:48;3160:83:5;;;17689:21:48;17746:2;17726:18;;;17719:30;17785:34;17765:18;;;17758:62;-1:-1:-1;;;17836:18:48;;;17829:39;17885:19;;3160:83:5;17505:405:48;3160:83:5;3254:30;3301:8;:15;-1:-1:-1;;;;;3287:30:5;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3287:30:5;;3254:63;;3333:9;3328:120;3352:8;:15;3348:1;:19;3328:120;;;3407:30;3417:8;3426:1;3417:11;;;;;;;;:::i;:::-;;;;;;;3430:3;3434:1;3430:6;;;;;;;;:::i;:::-;;;;;;;3407:9;:30::i;:::-;3388:13;3402:1;3388:16;;;;;;;;:::i;:::-;;;;;;;;;;:49;3369:3;;;:::i;:::-;;;3328:120;;;-1:-1:-1;3465:13:5;2977:508;-1:-1:-1;;;2977:508:5:o;4850:1270:32:-;1482:19:3;:17;:19::i;:::-;1815:1:4::1;2569:7;;:19;;2561:63;;;;-1:-1:-1::0;;;2561:63:4::1;;;;;;;:::i;:::-;1815:1;2699:7;:18:::0;3248:1:32::2;3219:17:::0;;;:7:::2;:17;::::0;;;;;5100:8;;-1:-1:-1;;;;;3219:17:32::2;3211:79;;;::::0;-1:-1:-1;;;3211:79:32;;18117:2:48;3211:79:32::2;::::0;::::2;18099:21:48::0;18156:2;18136:18;;;18129:30;18195:34;18175:18;;;18168:62;-1:-1:-1;;;18246:18:48;;;18239:33;18289:19;;3211:79:32::2;17915:399:48::0;3211:79:32::2;5140:1:::3;5128:9;-1:-1:-1::0;;;;;5128:13:32::3;;5120:55;;;::::0;-1:-1:-1;;;5120:55:32;;18521:2:48;5120:55:32::3;::::0;::::3;18503:21:48::0;18560:2;18540:18;;;18533:30;18599:31;18579:18;;;18572:59;18648:18;;5120:55:32::3;18319:353:48::0;5120:55:32::3;5203:1;5193:7;-1:-1:-1::0;;;;;5193:11:32::3;;5185:51;;;::::0;-1:-1:-1;;;5185:51:32;;18879:2:48;5185:51:32::3;::::0;::::3;18861:21:48::0;18918:2;18898:18;;;18891:30;18957:29;18937:18;;;18930:57;19004:18;;5185:51:32::3;18677:351:48::0;5185:51:32::3;5265:1;5254:8;:12;5246:53;;;::::0;-1:-1:-1;;;5246:53:32;;19235:2:48;5246:53:32::3;::::0;::::3;19217:21:48::0;19274:2;19254:18;;;19247:30;19313;19293:18;;;19286:58;19361:18;;5246:53:32::3;19033:352:48::0;5246:53:32::3;5334:1;5317:14;:18;5309:58;;;::::0;-1:-1:-1;;;5309:58:32;;19592:2:48;5309:58:32::3;::::0;::::3;19574:21:48::0;19631:2;19611:18;;;19604:30;19670:29;19650:18;;;19643:57;19717:18;;5309:58:32::3;19390:351:48::0;5309:58:32::3;-1:-1:-1::0;;;;;5385:26:32;::::3;5377:71;;;::::0;-1:-1:-1;;;5377:71:32;;19948:2:48;5377:71:32::3;::::0;::::3;19930:21:48::0;;;19967:18;;;19960:30;20026:34;20006:18;;;19999:62;20078:18;;5377:71:32::3;19746:356:48::0;5377:71:32::3;-1:-1:-1::0;;;;;5468:21:32;::::3;;::::0;;;:10:::3;:21;::::0;;;;;;;-1:-1:-1;;;;;5468:35:32;::::3;::::0;;;;;;;;::::3;;5467:36;5459:77;;;;-1:-1:-1::0;;;5459:77:32::3;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5555:27:32;;::::3;;::::0;;;:16:::3;:27;::::0;;;;;;;:36;;::::3;::::0;;;;;;;::::3;;5554:37;5546:78;;;;-1:-1:-1::0;;;5546:78:32::3;;;;;;;:::i;:::-;5651:125;5672:70;5683:9;5694:7;5703:8;5713:12;5727:14;5672:10;:70::i;:::-;5756:10;;5651:7;:125::i;:::-;5643:168;;;::::0;-1:-1:-1;;;5643:168:32;;20666:2:48;5643:168:32::3;::::0;::::3;20648:21:48::0;20705:2;20685:18;;;20678:30;20744:32;20724:18;;;20717:60;20794:18;;5643:168:32::3;20464:354:48::0;5643:168:32::3;-1:-1:-1::0;;;;;5822:21:32;;::::3;;::::0;;;:10:::3;:21;::::0;;;;;;;-1:-1:-1;;;;;5822:35:32;::::3;::::0;;;;;;;;;:42;;5860:4:::3;-1:-1:-1::0;;5822:42:32;;::::3;::::0;::::3;::::0;;;5874:27;;;:16:::3;:27:::0;;;;;:36;;::::3;::::0;;;;;;;;;;:43;;;;::::3;;::::0;;;5932:72;;20995:58:48;;;21069:18;;;21062:34;;;5822:35:32;;5965:8;;5874:36;;5932:72:::3;::::0;20968:18:48;5932:72:32::3;;;;;;;6015:21;::::0;;;:11:::3;:21;::::0;;;;:39;;6040:14;;6015:21;:39:::3;::::0;6040:14;;6015:39:::3;:::i;:::-;;;;;;;;6064:49;6070:12;6084:8;6094:14;6064:49;;;;;;;;;;;::::0;:5:::3;:49::i;:::-;-1:-1:-1::0;;1772:1:4::1;2872:7;:22:::0;-1:-1:-1;;;;;;4850:1270:32:o;2071:101:0:-;1334:13;:11;:13::i;:::-;2135:30:::1;2162:1;2135:18;:30::i;7889:271:32:-:0;1815:1:4;2569:7;;:19;;2561:63;;;;-1:-1:-1;;;2561:63:4;;;;;;;:::i;:::-;1815:1;2699:7;:18;3369:17:32::1;::::0;;;:7:::1;:17;::::0;;;;8049:8;;3387:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;;;3369:31:32::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;3369:31:32;;::::1;;3361:90;;;;-1:-1:-1::0;;;3361:90:32::1;;;;;;;:::i;:::-;8069:21:::2;::::0;;;:11:::2;:21;::::0;;;;:32;;8094:7;;8069:21;:32:::2;::::0;8094:7;;8069:32:::2;:::i;:::-;::::0;;;-1:-1:-1;8111:42:32::2;::::0;-1:-1:-1;8123:3:32;8128:8;8138:7;8147:5;8111:11:::2;:42::i;:::-;-1:-1:-1::0;;1772:1:4;2872:7;:22;-1:-1:-1;;;7889:271:32:o;7607:59::-;1334:13:0;:11;:13::i;:::-;7651:8:32::1;:6;:8::i;6126:953::-:0;1482:19:3;:17;:19::i;:::-;1815:1:4::1;2569:7;;:19;;2561:63;;;;-1:-1:-1::0;;;2561:63:4::1;;;;;;;:::i;:::-;1815:1;2699:7;:18:::0;-1:-1:-1;;;;;6329:13:32;::::2;6321:55;;;::::0;-1:-1:-1;;;6321:55:32;;18521:2:48;6321:55:32::2;::::0;::::2;18503:21:48::0;18560:2;18540:18;;;18533:30;18599:31;18579:18;;;18572:59;18648:18;;6321:55:32::2;18319:353:48::0;6321:55:32::2;6404:1;6394:7;-1:-1:-1::0;;;;;6394:11:32::2;;6386:51;;;::::0;-1:-1:-1;;;6386:51:32;;18879:2:48;6386:51:32::2;::::0;::::2;18861:21:48::0;18918:2;18898:18;;;18891:30;18957:29;18937:18;;;18930:57;19004:18;;6386:51:32::2;18677:351:48::0;6386:51:32::2;-1:-1:-1::0;;;;;6455:26:32;::::2;6447:71;;;::::0;-1:-1:-1;;;6447:71:32;;19948:2:48;6447:71:32::2;::::0;::::2;19930:21:48::0;;;19967:18;;;19960:30;20026:34;20006:18;;;19999:62;20078:18;;6447:71:32::2;19746:356:48::0;6447:71:32::2;6529:12;6544:49;6560:9;6571:7;6580:12;6544:15;:49::i;:::-;6612:26;::::0;;;:20:::2;:26;::::0;;;;;6529:64;;-1:-1:-1;6612:26:32::2;;6611:27;6603:68;;;;-1:-1:-1::0;;;6603:68:32::2;;;;;;;:::i;:::-;6706:1;::::0;6763:59:::2;6784:4:::0;6802:10;;6763:7:::2;:59::i;:::-;6755:102;;;::::0;-1:-1:-1;;;6755:102:32;;20666:2:48;6755:102:32::2;::::0;::::2;20648:21:48::0;20705:2;20685:18;;;20678:30;20744:32;20724:18;;;20717:60;20794:18;;6755:102:32::2;20464:354:48::0;6755:102:32::2;6868:26;::::0;;;:20:::2;:26;::::0;;;;;;;;:33;;-1:-1:-1;;6868:33:32::2;6897:4;6868:33;::::0;;6916:51;;-1:-1:-1;;;;;10219:32:48;;10201:51;;-1:-1:-1;;;;;6916:51:32;;::::2;::::0;;;::::2;::::0;::::2;::::0;10174:18:48;6916:51:32::2;;;;;;;6978:20;::::0;;;:11:::2;:20;::::0;;;;:37;;7002:13;;6978:20;:37:::2;::::0;7002:13;;6978:37:::2;:::i;:::-;;;;;;;;7025:47;7031:12;7045:7;7054:13;7025:47;;;;;;;;;;;::::0;:5:::2;:47::i;3553:153:5:-:0;3647:52;3666:12;:10;:12::i;:::-;3680:8;3690;3647:18;:52::i;:::-;3553:153;;:::o;7345:256:32:-;1334:13:0;:11;:13::i;:::-;-1:-1:-1;;;;;7428:28:32;::::1;7420:69;;;::::0;-1:-1:-1;;;7420:69:32;;21309:2:48;7420:69:32::1;::::0;::::1;21291:21:48::0;21348:2;21328:18;;;21321:30;21387;21367:18;;;21360:58;21435:18;;7420:69:32::1;21107:352:48::0;7420:69:32::1;7524:13;::::0;7504:50:::1;::::0;;-1:-1:-1;;;;;7524:13:32;;::::1;21676:34:48::0;;21746:15;;;21741:2;21726:18;;21719:43;7504:50:32::1;::::0;21611:18:48;7504:50:32::1;;;;;;;7564:13;:30:::0;;-1:-1:-1;;;;;;7564:30:32::1;-1:-1:-1::0;;;;;7564:30:32;;;::::1;::::0;;;::::1;::::0;;7345:256::o;4410:434::-;4518:7;1482:19:3;:17;:19::i;:::-;1815:1:4::1;2569:7;;:19;;2561:63;;;;-1:-1:-1::0;;;2561:63:4::1;;;;;;;:::i;:::-;1815:1;2699:7;:18;;;;4555:1:32::2;4537:14;;:19;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;4580:14:32::2;::::0;4613:12:::2;:10;:12::i;:::-;4598;::::0;;;:7:::2;:12;::::0;;;;;;;:27;;-1:-1:-1;;;;;;4598:27:32::2;-1:-1:-1::0;;;;;4598:27:32;;;::::2;::::0;;;::::2;::::0;;;4635:7:::2;:12:::0;;;;;-1:-1:-1;;4648:12:32::2;:10;:12::i;:::-;-1:-1:-1::0;;;;;4635:26:32::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;4635:26:32;:33;;-1:-1:-1;;4635:33:32::2;::::0;::::2;;::::0;;;::::2;::::0;;4672:44:::2;4678:12;:10;:12::i;:::-;4692:3;4697:14;4672:44;;;;;;;;;;;::::0;:5:::2;:44::i;:::-;4720:16;::::0;;;:11:::2;:16;::::0;;;;:33;;;4797:12:::2;:10;:12::i;:::-;-1:-1:-1::0;;;;;4768:58:32::2;4792:3;4768:58;4811:14;4768:58;;;;1191:25:48::0;;1179:2;1164:18;;1045:177;4768:58:32::2;;;;;;;;1772:1:4::1;2872:7;:22:::0;4837:3:32;4410:434;-1:-1:-1;;4410:434:32:o;8661:259::-;3369:17;;;;:7;:17;;;;;8740:8;;3387:12;:10;:12::i;:::-;-1:-1:-1;;;;;3369:31:32;;;;;;;;;;;;-1:-1:-1;3369:31:32;;;;3361:90;;;;-1:-1:-1;;;3361:90:32;;;;;;;:::i;:::-;-1:-1:-1;;;;;8768:20:32;::::1;8760:61;;;::::0;-1:-1:-1;;;8760:61:32;;21309:2:48;8760:61:32::1;::::0;::::1;21291:21:48::0;21348:2;21328:18;;;21321:30;21387;21367:18;;;21360:58;21435:18;;8760:61:32::1;21107:352:48::0;8760:61:32::1;8831:17;::::0;;;:7:::1;:17;::::0;;;;;;;-1:-1:-1;;;;;8831:25:32;::::1;::::0;;;;;;;;;;:32;;-1:-1:-1;;8831:32:32::1;8859:4;8831:32;::::0;;8878:35;;21947:25:48;;;21988:18;;;21981:60;;;;8878:35:32::1;::::0;21920:18:48;8878:35:32::1;;;;;;;8661:259:::0;;;:::o;4006:395:5:-;4214:12;:10;:12::i;:::-;-1:-1:-1;;;;;4206:20:5;:4;-1:-1:-1;;;;;4206:20:5;;:60;;;;4230:36;4247:4;4253:12;:10;:12::i;4230:36::-;4185:154;;;;-1:-1:-1;;;4185:154:5;;;;;;;:::i;:::-;4349:45;4367:4;4373:2;4377;4381:6;4389:4;4349:17;:45::i;2321:198:0:-;1334:13;:11;:13::i;:::-;-1:-1:-1;;;;;2409:22:0;::::1;2401:73;;;::::0;-1:-1:-1;;;2401:73:0;;22254:2:48;2401:73:0::1;::::0;::::1;22236:21:48::0;22293:2;22273:18;;;22266:30;22332:34;22312:18;;;22305:62;-1:-1:-1;;;22383:18:48;;;22376:36;22429:19;;2401:73:0::1;22052:402:48::0;2401:73:0::1;2484:28;2503:8;2484:18;:28::i;3671:680:32:-:0;3111:19:2;3134:13;;;;;;3133:14;;3179:34;;;;-1:-1:-1;3197:12:2;;3212:1;3197:12;;;;:16;3179:34;3178:108;;;-1:-1:-1;3258:4:2;1476:19:9;:23;;;3219:66:2;;-1:-1:-1;3268:12:2;;;;;:17;3219:66;3157:201;;;;-1:-1:-1;;;3157:201:2;;22661:2:48;3157:201:2;;;22643:21:48;22700:2;22680:18;;;22673:30;22739:34;22719:18;;;22712:62;-1:-1:-1;;;22790:18:48;;;22783:44;22844:19;;3157:201:2;22459:410:48;3157:201:2;3368:12;:16;;-1:-1:-1;;3368:16:2;3383:1;3368:16;;;3394:65;;;;3428:13;:20;;-1:-1:-1;;3428:20:2;;;;;3394:65;-1:-1:-1;;;;;3776:28:32;::::1;3768:101;;;::::0;-1:-1:-1;;;3768:101:32;;23076:2:48;3768:101:32::1;::::0;::::1;23058:21:48::0;23115:2;23095:18;;;23088:30;23154:34;23134:18;;;23127:62;23225:30;23205:18;;;23198:58;23273:19;;3768:101:32::1;22874:424:48::0;3768:101:32::1;3879:16;:14;:16::i;:::-;3905:17;:15;:17::i;:::-;3932:37;;;;;;;;;;;;;;-1:-1:-1::0;;;3932:37:32::1;;::::0;::::1;;;;;;;;;;;;;-1:-1:-1::0;;;3932:37:32::1;;::::0;:13:::1;:37::i;:::-;3979:24;:22;:24::i;:::-;4013:20;4028:4;;4013:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;4013:14:32::1;::::0;-1:-1:-1;;;4013:20:32:i:1;:::-;4043:13;:30:::0;;-1:-1:-1;;;;;;4043:30:32::1;-1:-1:-1::0;;;;;4043:30:32;::::1;;::::0;;-1:-1:-1;4092:14:32::1;:18:::0;;;4167:12:::1;:10;:12::i;:::-;4152;::::0;;;:7:::1;:12;::::0;;;;;;;:27;;-1:-1:-1;;;;;;4152:27:32::1;-1:-1:-1::0;;;;;4152:27:32;;;::::1;::::0;;;::::1;::::0;;;4189:7:::1;:12:::0;;;;;-1:-1:-1;;4202:12:32::1;:10;:12::i;:::-;-1:-1:-1::0;;;;;4189:26:32::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;4189:26:32;:33;;-1:-1:-1;;4189:33:32::1;::::0;::::1;;::::0;;;::::1;::::0;;4226:31:::1;4232:12;:10;:12::i;:::-;4246:3;4251:1;4226:31;;;;;;;;;;;::::0;:5:::1;:31::i;:::-;4261:16;::::0;;;:11:::1;:16;::::0;;;;;;;4280:1:::1;4261:20:::0;;4297:47;;21676:34:48;;;-1:-1:-1;;;;;21746:15:48;;21726:18;;;21719:43;;;;4297:47:32::1;::::0;21611:18:48;4297:47:32::1;;;;;;;3758:593;3483:14:2::0;3479:99;;;3529:5;3513:21;;-1:-1:-1;;3513:21:2;;;3553:14;;-1:-1:-1;23455:36:48;;3553:14:2;;23443:2:48;23428:18;3553:14:2;;;;;;;3479:99;3101:483;3671:680:32;;;:::o;1599:130:0:-;1673:12;:10;:12::i;:::-;-1:-1:-1;;;;;1662:23:0;:7;1513:6;;-1:-1:-1;;;;;1513:6:0;;1441:85;1662:7;-1:-1:-1;;;;;1662:23:0;;1654:68;;;;-1:-1:-1;;;1654:68:0;;23704:2:48;1654:68:0;;;23686:21:48;;;23723:18;;;23716:30;23782:34;23762:18;;;23755:62;23834:18;;1654:68:0;23502:356:48;8581:86:5;8647:13;;;;:4;;:13;;;;;:::i;2348:103::-;2408:13;2440:4;2433:11;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2348:103;;;:::o;403:703:11:-;459:13;676:10;672:51;;-1:-1:-1;;702:10:11;;;;;;;;;;;;-1:-1:-1;;;702:10:11;;;;;403:703::o;672:51::-;747:5;732:12;786:75;793:9;;786:75;;818:8;;;;:::i;:::-;;-1:-1:-1;840:10:11;;-1:-1:-1;848:2:11;840:10;;:::i;:::-;;;786:75;;;870:19;902:6;-1:-1:-1;;;;;892:17:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;892:17:11;;870:39;;919:150;926:10;;919:150;;952:11;962:1;952:11;;:::i;:::-;;-1:-1:-1;1020:10:11;1028:2;1020:5;:10;:::i;:::-;1007:24;;:2;:24;:::i;:::-;994:39;;977:6;984;977:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;977:56:11;;;;;;;;-1:-1:-1;1047:11:11;1056:2;1047:11;;:::i;:::-;;;919:150;;;1092:6;403:703;-1:-1:-1;;;;403:703:11:o;10542:231:32:-;10691:14;10728:38;:36;:38::i;:::-;10721:45;;10542:231;:::o;10139:791:5:-;-1:-1:-1;;;;;10311:16:5;;10303:62;;;;-1:-1:-1;;;10303:62:5;;;;;;;:::i;:::-;10397:7;:14;10383:3;:10;:28;10375:81;;;;-1:-1:-1;;;10375:81:5;;;;;;;:::i;:::-;10467:16;10486:12;:10;:12::i;:::-;10467:31;;10591:9;10586:101;10610:3;:10;10606:1;:14;10586:101;;;10666:7;10674:1;10666:10;;;;;;;;:::i;:::-;;;;;;;10641:9;:17;10651:3;10655:1;10651:6;;;;;;;;:::i;:::-;;;;;;;10641:17;;;;;;;;;;;:21;10659:2;-1:-1:-1;;;;;10641:21:5;-1:-1:-1;;;;;10641:21:5;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;10622:3:5;;-1:-1:-1;10622:3:5;;;:::i;:::-;;;;10586:101;;;;10738:2;-1:-1:-1;;;;;10702:53:5;10734:1;-1:-1:-1;;;;;10702:53:5;10716:8;-1:-1:-1;;;;;10702:53:5;;10742:3;10747:7;10702:53;;;;;;;:::i;:::-;;;;;;;;10842:81;10878:8;10896:1;10900:2;10904:3;10909:7;10918:4;10842:35;:81::i;6643:1115::-;6863:7;:14;6849:3;:10;:28;6841:81;;;;-1:-1:-1;;;6841:81:5;;;;;;;:::i;:::-;-1:-1:-1;;;;;6940:16:5;;6932:66;;;;-1:-1:-1;;;6932:66:5;;;;;;;:::i;:::-;7009:16;7028:12;:10;:12::i;:::-;7009:31;;7127:9;7122:411;7146:3;:10;7142:1;:14;7122:411;;;7177:10;7190:3;7194:1;7190:6;;;;;;;;:::i;:::-;;;;;;;7177:19;;7210:14;7227:7;7235:1;7227:10;;;;;;;;:::i;:::-;;;;;;;;;;;;7252:19;7274:13;;;:9;:13;;;;;;-1:-1:-1;;;;;7274:19:5;;;;;;;;;;;;7227:10;;-1:-1:-1;7315:21:5;;;;7307:76;;;;-1:-1:-1;;;7307:76:5;;;;;;;:::i;:::-;7425:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;7425:19:5;;;;;;;;;;7447:20;;;7425:42;;7495:17;;;;;;;:27;;7447:20;;7425:13;7495:27;;7447:20;;7495:27;:::i;:::-;;;;;;;;7163:370;;;7158:3;;;;:::i;:::-;;;7122:411;;;;7578:2;-1:-1:-1;;;;;7548:47:5;7572:4;-1:-1:-1;;;;;7548:47:5;7562:8;-1:-1:-1;;;;;7548:47:5;;7582:3;7587:7;7548:47;;;;;;;:::i;:::-;;;;;;;;7676:75;7712:8;7722:4;7728:2;7732:3;7737:7;7746:4;7676:35;:75::i;:::-;6831:927;6643:1115;;;;;:::o;2676:117:3:-;1729:16;:14;:16::i;:::-;2734:7:::1;:15:::0;;-1:-1:-1;;2734:15:3::1;::::0;;2764:22:::1;2773:12;:10;:12::i;:::-;2764:22;::::0;-1:-1:-1;;;;;10219:32:48;;;10201:51;;10189:2;10174:18;2764:22:3::1;;;;;;;2676:117::o:0;2010:106::-;1928:7;;;;2079:9;2071:38;;;;-1:-1:-1;;;2071:38:3;;27052:2:48;2071:38:3;;;27034:21:48;27091:2;27071:18;;;27064:30;-1:-1:-1;;;27110:18:48;;;27103:46;27166:18;;2071:38:3;26850:340:48;9561:541:32;9839:232;;;841:128;9839:232;;;27478:25:48;-1:-1:-1;;;;;27584:15:48;;;27564:18;;;27557:43;;;;27636:15;;;27616:18;;;27609:43;27668:18;;;27661:34;;;-1:-1:-1;;;;;27732:32:48;;27711:19;;;27704:61;27781:19;;;27774:35;;;9748:7:32;;9782:313;;27450:19:48;;9839:232:32;;;;;;;;;;;;;9812:273;;;;;;9782:16;:313::i;:::-;9767:328;9561:541;-1:-1:-1;;;;;;9561:541:32:o;11012:157::-;11149:13;;11115:30;;;;;;;;;;;;;;;;;;;;;;11092:4;;-1:-1:-1;;;;;11149:13:32;;11115:30;;11129:4;;11135:9;;;;;;11115:30;;11135:9;;;;11115:30;;;;;;;;;-1:-1:-1;11115:13:32;;-1:-1:-1;;;11115:30:32:i;:::-;-1:-1:-1;;;;;11115:47:32;;;11012:157;-1:-1:-1;;;;11012:157:32:o;9040:709:5:-;-1:-1:-1;;;;;9187:16:5;;9179:62;;;;-1:-1:-1;;;9179:62:5;;;;;;;:::i;:::-;9252:16;9271:12;:10;:12::i;:::-;9252:31;;9293:20;9316:21;9334:2;9316:17;:21::i;:::-;9293:44;;9347:24;9374:25;9392:6;9374:17;:25::i;:::-;9347:52;;9487:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;9487:17:5;;;;;;;;;:27;;9508:6;;9487:13;:27;;9508:6;;9487:27;:::i;:::-;;;;-1:-1:-1;;9529:52:5;;;27994:25:48;;;28050:2;28035:18;;28028:34;;;-1:-1:-1;;;;;9529:52:5;;;;9562:1;;9529:52;;;;;;27967:18:48;9529:52:5;;;;;;;9668:74;9699:8;9717:1;9721:2;9725;9729:6;9737:4;9668:30;:74::i;:::-;9169:580;;;9040:709;;;;:::o;2673:187:0:-;2765:6;;;-1:-1:-1;;;;;2781:17:0;;;-1:-1:-1;;;;;;2781:17:0;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;2429:115:3:-;1482:19;:17;:19::i;:::-;2488:7:::1;:14:::0;;-1:-1:-1;;2488:14:3::1;2498:4;2488:14;::::0;;2517:20:::1;2524:12;:10;:12::i;10108:428:32:-:0;10333:172;;;1031:95;10333:172;;;28300:25:48;-1:-1:-1;;;;;28406:15:48;;;28386:18;;;28379:43;;;;28458:15;;;28438:18;;;28431:43;-1:-1:-1;;;;;28510:32:48;;28490:18;;;28483:60;10242:7:32;;10276:253;;28272:19:48;;10333:172:32;28073:476:48;13320:323:5;13470:8;-1:-1:-1;;;;;13461:17:5;:5;-1:-1:-1;;;;;13461:17:5;;;13453:71;;;;-1:-1:-1;;;13453:71:5;;28756:2:48;13453:71:5;;;28738:21:48;28795:2;28775:18;;;28768:30;28834:34;28814:18;;;28807:62;-1:-1:-1;;;28885:18:48;;;28878:39;28934:19;;13453:71:5;28554:405:48;13453:71:5;-1:-1:-1;;;;;13534:25:5;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;13534:46:5;;;;;;;;;;13595:41;;2190::48;;;13595::5;;2163:18:48;13595:41:5;;;;;;;13320:323;;;:::o;5350:947::-;-1:-1:-1;;;;;5531:16:5;;5523:66;;;;-1:-1:-1;;;5523:66:5;;;;;;;:::i;:::-;5600:16;5619:12;:10;:12::i;:::-;5600:31;;5641:20;5664:21;5682:2;5664:17;:21::i;:::-;5641:44;;5695:24;5722:25;5740:6;5722:17;:25::i;:::-;5695:52;;5829:19;5851:13;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5851:19:5;;;;;;;;;;5888:21;;;;5880:76;;;;-1:-1:-1;;;5880:76:5;;;;;;;:::i;:::-;5990:13;;;;:9;:13;;;;;;;;-1:-1:-1;;;;;5990:19:5;;;;;;;;;;6012:20;;;5990:42;;6052:17;;;;;;;:27;;6012:20;;5990:13;6052:27;;6012:20;;6052:27;:::i;:::-;;;;-1:-1:-1;;6095:46:5;;;27994:25:48;;;28050:2;28035:18;;28028:34;;;-1:-1:-1;;;;;6095:46:5;;;;;;;;;;;;;;27967:18:48;6095:46:5;;;;;;;6222:68;6253:8;6263:4;6269:2;6273;6277:6;6285:4;6222:30;:68::i;:::-;5513:784;;;;5350:947;;;;;:::o;1003:95:0:-;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1065:26:0::1;:24;:26::i;1063:97:3:-:0;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1126:27:3::1;:25;:27::i;2306:147:13:-:0;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;2408:38:13::1;2432:4;2438:7;2408:23;:38::i;1853:111:4:-:0;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1923:34:4::1;:32;:34::i;1300:117:5:-:0;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1380:30:5::1;1405:4;1380:24;:30::i;769:448:1:-:0;831:14;739:17;-1:-1:-1;;;;;726:30:1;880:10;726:30;857:354;;;-1:-1:-1;;;1110:14:1;1106:23;1093:37;1089:2;1085:46;769:448;:::o;857:354::-;-1:-1:-1;929:10:10;;10542:231:32:o;857:354:1:-;769:448;:::o;16698:814:5:-;-1:-1:-1;;;;;16930:13:5;;1476:19:9;:23;16926:580:5;;16965:90;;-1:-1:-1;;;16965:90:5;;-1:-1:-1;;;;;16965:54:5;;;;;:90;;17020:8;;17030:4;;17036:3;;17041:7;;17050:4;;16965:90;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16965:90:5;;;;;;;;-1:-1:-1;;16965:90:5;;;;;;;;;;;;:::i;:::-;;;16961:535;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;17372:6;17365:14;;-1:-1:-1;;;17365:14:5;;;;;;;;:::i;16961:535::-;;;17419:62;;-1:-1:-1;;;17419:62:5;;31524:2:48;17419:62:5;;;31506:21:48;31563:2;31543:18;;;31536:30;31602:34;31582:18;;;31575:62;-1:-1:-1;;;31653:18:48;;;31646:50;31713:19;;17419:62:5;31322:416:48;16961:535:5;-1:-1:-1;;;;;;17134:71:5;;-1:-1:-1;;;17134:71:5;17130:168;;17229:50;;-1:-1:-1;;;17229:50:5;;;;;;;:::i;2188:106:3:-;1928:7;;;;2246:41;;;;-1:-1:-1;;;2246:41:3;;32354:2:48;2246:41:3;;;32336:21:48;32393:2;32373:18;;;32366:30;-1:-1:-1;;;32412:18:48;;;32405:50;32472:18;;2246:41:3;32152:344:48;3890:176:13;3967:7;3993:66;4026:20;:18;:20::i;:::-;4048:10;8710:57:12;;-1:-1:-1;;;8710:57:12;;;33325:27:48;33368:11;;;33361:27;;;33404:12;;;33397:28;;;8674:7:12;;33441:12:48;;8710:57:12;;;;;;;;;;;;8700:68;;;;;;8693:75;;8581:194;;;;;3759:227:29;3837:7;3857:17;3876:18;3898:27;3909:4;3915:9;3898:10;:27::i;:::-;3856:69;;;;3935:18;3947:5;3935:11;:18::i;17518:193:5:-;17637:16;;;17651:1;17637:16;;;;;;;;;17584;;17612:22;;17637:16;;;;;;;;;;;;-1:-1:-1;17637:16:5;17612:41;;17674:7;17663:5;17669:1;17663:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;17699:5;17518:193;-1:-1:-1;;17518:193:5:o;15945:747::-;-1:-1:-1;;;;;16152:13:5;;1476:19:9;:23;16148:538:5;;16187:83;;-1:-1:-1;;;16187:83:5;;-1:-1:-1;;;;;16187:49:5;;;;;:83;;16237:8;;16247:4;;16253:2;;16257:6;;16265:4;;16187:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16187:83:5;;;;;;;;-1:-1:-1;;16187:83:5;;;;;;;;;;;;:::i;:::-;;;16183:493;;;;:::i;:::-;-1:-1:-1;;;;;;16319:66:5;;-1:-1:-1;;;16319:66:5;16315:163;;16409:50;;-1:-1:-1;;;16409:50:5;;;;;;;:::i;1104:111:0:-;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1176:32:0::1;1195:12;:10;:12::i;:::-;1176:18;:32::i;1166:95:3:-:0;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1239:7:3::1;:15:::0;;-1:-1:-1;;1239:15:3::1;::::0;;1166:95::o;2459:297:13:-;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;2592:22:13;;::::1;::::0;;::::1;::::0;2648:25;;;;;::::1;::::0;2683:12:::1;:25:::0;;;;2718:15:::1;:31:::0;2459:297::o;1970:109:4:-;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;:::-;1772:1:4::1;2050:7;:22:::0;1970:109::o;1423:110:5:-;4910:13:2;;;;;;;4902:69;;;;-1:-1:-1;;;4902:69:2;;;;;;;:::i;2842:160:13:-;2895:7;2921:74;1595:95;2955:17;4386:12;;;4302:103;2955:17;4731:15;;3184:73;;;;;;35374:25:48;;;35415:18;;;35408:34;;;35458:18;;;35451:34;;;3228:13:13;35501:18:48;;;35494:34;3251:4:13;35544:19:48;;;35537:61;3148:7:13;;35346:19:48;;3184:73:13;;;;;;;;;;;;3174:84;;;;;;3167:91;;3008:257;;;;;;2243:730:29;2324:7;2333:12;2361:9;:16;2381:2;2361:22;2357:610;;;2697:4;2682:20;;2676:27;2746:4;2731:20;;2725:27;2803:4;2788:20;;2782:27;2399:9;2774:36;2844:25;2855:4;2774:36;2676:27;2725;2844:10;:25::i;:::-;2837:32;;;;;;;;;2357:610;-1:-1:-1;2916:1:29;;-1:-1:-1;2920:35:29;2357:610;2243:730;;;;;:::o;548:631::-;625:20;616:5;:29;;;;;;;;:::i;:::-;;612:561;;;548:631;:::o;612:561::-;721:29;712:5;:38;;;;;;;;:::i;:::-;;708:465;;;766:34;;-1:-1:-1;;;766:34:29;;33798:2:48;766:34:29;;;33780:21:48;33837:2;33817:18;;;33810:30;33876:26;33856:18;;;33849:54;33920:18;;766:34:29;33596:348:48;708:465:29;830:35;821:5;:44;;;;;;;;:::i;:::-;;817:356;;;881:41;;-1:-1:-1;;;881:41:29;;34151:2:48;881:41:29;;;34133:21:48;34190:2;34170:18;;;34163:30;34229:33;34209:18;;;34202:61;34280:18;;881:41:29;33949:355:48;817:356:29;952:30;943:5;:39;;;;;;;;:::i;:::-;;939:234;;;998:44;;-1:-1:-1;;;998:44:29;;34511:2:48;998:44:29;;;34493:21:48;34550:2;34530:18;;;34523:30;34589:34;34569:18;;;34562:62;-1:-1:-1;;;34640:18:48;;;34633:32;34682:19;;998:44:29;34309:398:48;939:234:29;1072:30;1063:5;:39;;;;;;;;:::i;:::-;;1059:114;;;1118:44;;-1:-1:-1;;;1118:44:29;;34914:2:48;1118:44:29;;;34896:21:48;34953:2;34933:18;;;34926:30;34992:34;34972:18;;;34965:62;-1:-1:-1;;;35043:18:48;;;35036:32;35085:19;;1118:44:29;34712:398:48;5167:1603:29;5293:7;;6217:66;6204:79;;6200:161;;;-1:-1:-1;6315:1:29;;-1:-1:-1;6319:30:29;6299:51;;6200:161;6374:1;:7;;6379:2;6374:7;;:18;;;;;6385:1;:7;;6390:2;6385:7;;6374:18;6370:100;;;-1:-1:-1;6424:1:29;;-1:-1:-1;6428:30:29;6408:51;;6370:100;6581:24;;;6564:14;6581:24;;;;;;;;;35836:25:48;;;35909:4;35897:17;;35877:18;;;35870:45;;;;35931:18;;;35924:34;;;35974:18;;;35967:34;;;6581:24:29;;35808:19:48;;6581:24:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6581:24:29;;-1:-1:-1;;6581:24:29;;;-1:-1:-1;;;;;;;6619:20:29;;6615:101;;6671:1;6675:29;6655:50;;;;;;;6615:101;6734:6;-1:-1:-1;6742:20:29;;-1:-1:-1;5167:1603:29;;;;;;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:127:48;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:258;218:1;228:113;242:6;239:1;236:13;228:113;;;318:11;;;312:18;299:11;;;292:39;264:2;257:10;228:113;;;359:6;356:1;353:13;350:48;;;-1:-1:-1;;394:1:48;376:16;;369:27;146:258::o;409:274::-;538:3;576:6;570:13;592:53;638:6;633:3;626:4;618:6;614:17;592:53;:::i;:::-;661:16;;;;;409:274;-1:-1:-1;;409:274:48:o;1227:173::-;1295:20;;-1:-1:-1;;;;;1344:31:48;;1334:42;;1324:70;;1390:1;1387;1380:12;1324:70;1227:173;;;:::o;1405:254::-;1473:6;1481;1534:2;1522:9;1513:7;1509:23;1505:32;1502:52;;;1550:1;1547;1540:12;1502:52;1573:29;1592:9;1573:29;:::i;:::-;1563:39;1649:2;1634:18;;;;1621:32;;-1:-1:-1;;;1405:254:48:o;1664:131::-;-1:-1:-1;;;;;;1738:32:48;;1728:43;;1718:71;;1785:1;1782;1775:12;1800:245;1858:6;1911:2;1899:9;1890:7;1886:23;1882:32;1879:52;;;1927:1;1924;1917:12;1879:52;1966:9;1953:23;1985:30;2009:5;1985:30;:::i;:::-;2034:5;1800:245;-1:-1:-1;;;1800:245:48:o;2242:249::-;2352:2;2333:13;;-1:-1:-1;;2329:27:48;2317:40;;-1:-1:-1;;;;;2372:34:48;;2408:22;;;2369:62;2366:88;;;2434:18;;:::i;:::-;2470:2;2463:22;-1:-1:-1;;2242:249:48:o;2496:469::-;2561:5;-1:-1:-1;;;;;2587:6:48;2584:30;2581:56;;;2617:18;;:::i;:::-;2666:2;2660:9;2678:69;2735:2;2714:15;;-1:-1:-1;;2710:29:48;2741:4;2706:40;2660:9;2678:69;:::i;:::-;2765:6;2756:15;;2795:6;2787;2780:22;2835:3;2826:6;2821:3;2817:16;2814:25;2811:45;;;2852:1;2849;2842:12;2811:45;2902:6;2897:3;2890:4;2882:6;2878:17;2865:44;2957:1;2950:4;2941:6;2933;2929:19;2925:30;2918:41;;2496:469;;;;;:::o;2970:451::-;3039:6;3092:2;3080:9;3071:7;3067:23;3063:32;3060:52;;;3108:1;3105;3098:12;3060:52;3148:9;3135:23;-1:-1:-1;;;;;3173:6:48;3170:30;3167:50;;;3213:1;3210;3203:12;3167:50;3236:22;;3289:4;3281:13;;3277:27;-1:-1:-1;3267:55:48;;3318:1;3315;3308:12;3267:55;3341:74;3407:7;3402:2;3389:16;3384:2;3380;3376:11;3341:74;:::i;3426:180::-;3485:6;3538:2;3526:9;3517:7;3513:23;3509:32;3506:52;;;3554:1;3551;3544:12;3506:52;-1:-1:-1;3577:23:48;;3426:180;-1:-1:-1;3426:180:48:o;3978:258::-;4020:3;4058:5;4052:12;4085:6;4080:3;4073:19;4101:63;4157:6;4150:4;4145:3;4141:14;4134:4;4127:5;4123:16;4101:63;:::i;:::-;4218:2;4197:15;-1:-1:-1;;4193:29:48;4184:39;;;;4225:4;4180:50;;3978:258;-1:-1:-1;;3978:258:48:o;4241:220::-;4390:2;4379:9;4372:21;4353:4;4410:45;4451:2;4440:9;4436:18;4428:6;4410:45;:::i;4466:254::-;4534:6;4542;4595:2;4583:9;4574:7;4570:23;4566:32;4563:52;;;4611:1;4608;4601:12;4563:52;4647:9;4634:23;4624:33;;4676:38;4710:2;4699:9;4695:18;4676:38;:::i;:::-;4666:48;;4466:254;;;;;:::o;4725:183::-;4785:4;-1:-1:-1;;;;;4810:6:48;4807:30;4804:56;;;4840:18;;:::i;:::-;-1:-1:-1;4885:1:48;4881:14;4897:4;4877:25;;4725:183::o;4913:724::-;4967:5;5020:3;5013:4;5005:6;5001:17;4997:27;4987:55;;5038:1;5035;5028:12;4987:55;5074:6;5061:20;5100:4;5123:43;5163:2;5123:43;:::i;:::-;5195:2;5189:9;5207:31;5235:2;5227:6;5207:31;:::i;:::-;5273:18;;;5365:1;5361:10;;;;5349:23;;5345:32;;;5307:15;;;;-1:-1:-1;5389:15:48;;;5386:35;;;5417:1;5414;5407:12;5386:35;5453:2;5445:6;5441:15;5465:142;5481:6;5476:3;5473:15;5465:142;;;5547:17;;5535:30;;5585:12;;;;5498;;5465:142;;;-1:-1:-1;5625:6:48;4913:724;-1:-1:-1;;;;;;4913:724:48:o;5642:221::-;5684:5;5737:3;5730:4;5722:6;5718:17;5714:27;5704:55;;5755:1;5752;5745:12;5704:55;5777:80;5853:3;5844:6;5831:20;5824:4;5816:6;5812:17;5777:80;:::i;5868:868::-;6013:6;6021;6029;6037;6090:3;6078:9;6069:7;6065:23;6061:33;6058:53;;;6107:1;6104;6097:12;6058:53;6130:29;6149:9;6130:29;:::i;:::-;6120:39;;6210:2;6199:9;6195:18;6182:32;-1:-1:-1;;;;;6274:2:48;6266:6;6263:14;6260:34;;;6290:1;6287;6280:12;6260:34;6313:61;6366:7;6357:6;6346:9;6342:22;6313:61;:::i;:::-;6303:71;;6427:2;6416:9;6412:18;6399:32;6383:48;;6456:2;6446:8;6443:16;6440:36;;;6472:1;6469;6462:12;6440:36;6495:63;6550:7;6539:8;6528:9;6524:24;6495:63;:::i;:::-;6485:73;;6611:2;6600:9;6596:18;6583:32;6567:48;;6640:2;6630:8;6627:16;6624:36;;;6656:1;6653;6646:12;6624:36;;6679:51;6722:7;6711:8;6700:9;6696:24;6679:51;:::i;:::-;6669:61;;;5868:868;;;;;;;:::o;6741:943::-;6895:6;6903;6911;6919;6927;6980:3;6968:9;6959:7;6955:23;6951:33;6948:53;;;6997:1;6994;6987:12;6948:53;7020:29;7039:9;7020:29;:::i;:::-;7010:39;;7068:38;7102:2;7091:9;7087:18;7068:38;:::i;:::-;7058:48;;7157:2;7146:9;7142:18;7129:32;-1:-1:-1;;;;;7221:2:48;7213:6;7210:14;7207:34;;;7237:1;7234;7227:12;7207:34;7260:61;7313:7;7304:6;7293:9;7289:22;7260:61;:::i;:::-;7250:71;;7374:2;7363:9;7359:18;7346:32;7330:48;;7403:2;7393:8;7390:16;7387:36;;;7419:1;7416;7409:12;7387:36;7442:63;7497:7;7486:8;7475:9;7471:24;7442:63;:::i;:::-;7432:73;;7558:3;7547:9;7543:19;7530:33;7514:49;;7588:2;7578:8;7575:16;7572:36;;;7604:1;7601;7594:12;7572:36;;7627:51;7670:7;7659:8;7648:9;7644:24;7627:51;:::i;:::-;7617:61;;;6741:943;;;;;;;;:::o;7689:179::-;7756:20;;-1:-1:-1;;;;;7805:38:48;;7795:49;;7785:77;;7858:1;7855;7848:12;7873:258;7940:6;7948;8001:2;7989:9;7980:7;7976:23;7972:32;7969:52;;;8017:1;8014;8007:12;7969:52;8040:28;8058:9;8040:28;:::i;:::-;8030:38;;8087;8121:2;8110:9;8106:18;8087:38;:::i;8136:1208::-;8254:6;8262;8315:2;8303:9;8294:7;8290:23;8286:32;8283:52;;;8331:1;8328;8321:12;8283:52;8371:9;8358:23;-1:-1:-1;;;;;8441:2:48;8433:6;8430:14;8427:34;;;8457:1;8454;8447:12;8427:34;8495:6;8484:9;8480:22;8470:32;;8540:7;8533:4;8529:2;8525:13;8521:27;8511:55;;8562:1;8559;8552:12;8511:55;8598:2;8585:16;8620:4;8643:43;8683:2;8643:43;:::i;:::-;8715:2;8709:9;8727:31;8755:2;8747:6;8727:31;:::i;:::-;8793:18;;;8881:1;8877:10;;;;8869:19;;8865:28;;;8827:15;;;;-1:-1:-1;8905:19:48;;;8902:39;;;8937:1;8934;8927:12;8902:39;8961:11;;;;8981:148;8997:6;8992:3;8989:15;8981:148;;;9063:23;9082:3;9063:23;:::i;:::-;9051:36;;9014:12;;;;9107;;;;8981:148;;;9148:6;-1:-1:-1;;9192:18:48;;9179:32;;-1:-1:-1;;9223:16:48;;;9220:36;;;9252:1;9249;9242:12;9220:36;;9275:63;9330:7;9319:8;9308:9;9304:24;9275:63;:::i;:::-;9265:73;;;8136:1208;;;;;:::o;9349:435::-;9402:3;9440:5;9434:12;9467:6;9462:3;9455:19;9493:4;9522:2;9517:3;9513:12;9506:19;;9559:2;9552:5;9548:14;9580:1;9590:169;9604:6;9601:1;9598:13;9590:169;;;9665:13;;9653:26;;9699:12;;;;9734:15;;;;9626:1;9619:9;9590:169;;;-1:-1:-1;9775:3:48;;9349:435;-1:-1:-1;;;;;9349:435:48:o;9789:261::-;9968:2;9957:9;9950:21;9931:4;9988:56;10040:2;10029:9;10025:18;10017:6;9988:56;:::i;10263:186::-;10322:6;10375:2;10363:9;10354:7;10350:23;10346:32;10343:52;;;10391:1;10388;10381:12;10343:52;10414:29;10433:9;10414:29;:::i;10454:347::-;10505:8;10515:6;10569:3;10562:4;10554:6;10550:17;10546:27;10536:55;;10587:1;10584;10577:12;10536:55;-1:-1:-1;10610:20:48;;-1:-1:-1;;;;;10642:30:48;;10639:50;;;10685:1;10682;10675:12;10639:50;10722:4;10714:6;10710:17;10698:29;;10774:3;10767:4;10758:6;10750;10746:19;10742:30;10739:39;10736:59;;;10791:1;10788;10781:12;10806:766;10919:6;10927;10935;10943;10951;10959;10967;11020:3;11008:9;10999:7;10995:23;10991:33;10988:53;;;11037:1;11034;11027:12;10988:53;11060:28;11078:9;11060:28;:::i;:::-;11050:38;;11107:37;11140:2;11129:9;11125:18;11107:37;:::i;:::-;11097:47;;11191:2;11180:9;11176:18;11163:32;11153:42;;11242:2;11231:9;11227:18;11214:32;11204:42;;11265:39;11299:3;11288:9;11284:19;11265:39;:::i;:::-;11255:49;;11355:3;11344:9;11340:19;11327:33;-1:-1:-1;;;;;11375:6:48;11372:30;11369:50;;;11415:1;11412;11405:12;11369:50;11454:58;11504:7;11495:6;11484:9;11480:22;11454:58;:::i;:::-;10806:766;;;;-1:-1:-1;10806:766:48;;-1:-1:-1;10806:766:48;;;;11428:84;;-1:-1:-1;;;10806:766:48:o;11577:531::-;11672:6;11680;11688;11696;11749:3;11737:9;11728:7;11724:23;11720:33;11717:53;;;11766:1;11763;11756:12;11717:53;11789:29;11808:9;11789:29;:::i;:::-;11779:39;;11865:2;11854:9;11850:18;11837:32;11827:42;;11916:2;11905:9;11901:18;11888:32;11878:42;;11971:2;11960:9;11956:18;11943:32;-1:-1:-1;;;;;11990:6:48;11987:30;11984:50;;;12030:1;12027;12020:12;11984:50;12053:49;12094:7;12085:6;12074:9;12070:22;12053:49;:::i;12113:628::-;12208:6;12216;12224;12232;12240;12293:3;12281:9;12272:7;12268:23;12264:33;12261:53;;;12310:1;12307;12300:12;12261:53;12333:28;12351:9;12333:28;:::i;:::-;12323:38;;12380:37;12413:2;12402:9;12398:18;12380:37;:::i;:::-;12370:47;;12436:38;12470:2;12459:9;12455:18;12436:38;:::i;:::-;12426:48;;12525:2;12514:9;12510:18;12497:32;-1:-1:-1;;;;;12544:6:48;12541:30;12538:50;;;12584:1;12581;12574:12;12538:50;12623:58;12673:7;12664:6;12653:9;12649:22;12623:58;:::i;:::-;12113:628;;;;-1:-1:-1;12113:628:48;;-1:-1:-1;12700:8:48;;12597:84;12113:628;-1:-1:-1;;;12113:628:48:o;12746:347::-;12811:6;12819;12872:2;12860:9;12851:7;12847:23;12843:32;12840:52;;;12888:1;12885;12878:12;12840:52;12911:29;12930:9;12911:29;:::i;:::-;12901:39;;12990:2;12979:9;12975:18;12962:32;13037:5;13030:13;13023:21;13016:5;13013:32;13003:60;;13059:1;13056;13049:12;13003:60;13082:5;13072:15;;;12746:347;;;;;:::o;13098:256::-;13164:6;13172;13225:2;13213:9;13204:7;13200:23;13196:32;13193:52;;;13241:1;13238;13231:12;13193:52;13264:28;13282:9;13264:28;:::i;:::-;13254:38;;13311:37;13344:2;13333:9;13329:18;13311:37;:::i;13359:260::-;13427:6;13435;13488:2;13476:9;13467:7;13463:23;13459:32;13456:52;;;13504:1;13501;13494:12;13456:52;13527:29;13546:9;13527:29;:::i;13624:606::-;13728:6;13736;13744;13752;13760;13813:3;13801:9;13792:7;13788:23;13784:33;13781:53;;;13830:1;13827;13820:12;13781:53;13853:29;13872:9;13853:29;:::i;:::-;13843:39;;13901:38;13935:2;13924:9;13920:18;13901:38;:::i;:::-;13891:48;;13986:2;13975:9;13971:18;13958:32;13948:42;;14037:2;14026:9;14022:18;14009:32;13999:42;;14092:3;14081:9;14077:19;14064:33;-1:-1:-1;;;;;14112:6:48;14109:30;14106:50;;;14152:1;14149;14142:12;14106:50;14175:49;14216:7;14207:6;14196:9;14192:22;14175:49;:::i;14235:484::-;14315:6;14323;14331;14384:2;14372:9;14363:7;14359:23;14355:32;14352:52;;;14400:1;14397;14390:12;14352:52;14423:29;14442:9;14423:29;:::i;:::-;14413:39;;14503:2;14492:9;14488:18;14475:32;-1:-1:-1;;;;;14522:6:48;14519:30;14516:50;;;14562:1;14559;14552:12;14516:50;14601:58;14651:7;14642:6;14631:9;14627:22;14601:58;:::i;:::-;14235:484;;14678:8;;-1:-1:-1;14575:84:48;;-1:-1:-1;;;;14235:484:48:o;15135:637::-;15415:3;15453:6;15447:13;15469:53;15515:6;15510:3;15503:4;15495:6;15491:17;15469:53;:::i;:::-;15585:13;;15544:16;;;;15607:57;15585:13;15544:16;15641:4;15629:17;;15607:57;:::i;:::-;-1:-1:-1;;;15686:20:48;;15715:22;;;15764:1;15753:13;;15135:637;-1:-1:-1;;;;15135:637:48:o;15777:355::-;15979:2;15961:21;;;16018:2;15998:18;;;15991:30;16057:33;16052:2;16037:18;;16030:61;16123:2;16108:18;;15777:355::o;16137:127::-;16198:10;16193:3;16189:20;16186:1;16179:31;16229:4;16226:1;16219:15;16253:4;16250:1;16243:15;16269:410;16471:2;16453:21;;;16510:2;16490:18;;;16483:30;16549:34;16544:2;16529:18;;16522:62;-1:-1:-1;;;16615:2:48;16600:18;;16593:44;16669:3;16654:19;;16269:410::o;16684:127::-;16745:10;16740:3;16736:20;16733:1;16726:31;16776:4;16773:1;16766:15;16800:4;16797:1;16790:15;16816:128;16856:3;16887:1;16883:6;16880:1;16877:13;16874:39;;;16893:18;;:::i;:::-;-1:-1:-1;16929:9:48;;16816:128::o;16949:135::-;16988:3;-1:-1:-1;;17009:17:48;;17006:43;;;17029:18;;:::i;:::-;-1:-1:-1;17076:1:48;17065:13;;16949:135::o;17089:411::-;17291:2;17273:21;;;17330:2;17310:18;;;17303:30;17369:34;17364:2;17349:18;;17342:62;-1:-1:-1;;;17435:2:48;17420:18;;17413:45;17490:3;17475:19;;17089:411::o;20107:352::-;20309:2;20291:21;;;20348:2;20328:18;;;20321:30;20387;20382:2;20367:18;;20360:58;20450:2;20435:18;;20107:352::o;23863:380::-;23942:1;23938:12;;;;23985;;;24006:61;;24060:4;24052:6;24048:17;24038:27;;24006:61;24113:2;24105:6;24102:14;24082:18;24079:38;24076:161;;;24159:10;24154:3;24150:20;24147:1;24140:31;24194:4;24191:1;24184:15;24222:4;24219:1;24212:15;24076:161;;23863:380;;;:::o;24248:127::-;24309:10;24304:3;24300:20;24297:1;24290:31;24340:4;24337:1;24330:15;24364:4;24361:1;24354:15;24380:120;24420:1;24446;24436:35;;24451:18;;:::i;:::-;-1:-1:-1;24485:9:48;;24380:120::o;24505:125::-;24545:4;24573:1;24570;24567:8;24564:34;;;24578:18;;:::i;:::-;-1:-1:-1;24615:9:48;;24505:125::o;24635:112::-;24667:1;24693;24683:35;;24698:18;;:::i;:::-;-1:-1:-1;24732:9:48;;24635:112::o;24752:397::-;24954:2;24936:21;;;24993:2;24973:18;;;24966:30;25032:34;25027:2;25012:18;;25005:62;-1:-1:-1;;;25098:2:48;25083:18;;25076:31;25139:3;25124:19;;24752:397::o;25154:404::-;25356:2;25338:21;;;25395:2;25375:18;;;25368:30;25434:34;25429:2;25414:18;;25407:62;-1:-1:-1;;;25500:2:48;25485:18;;25478:38;25548:3;25533:19;;25154:404::o;25563:465::-;25820:2;25809:9;25802:21;25783:4;25846:56;25898:2;25887:9;25883:18;25875:6;25846:56;:::i;:::-;25950:9;25942:6;25938:22;25933:2;25922:9;25918:18;25911:50;25978:44;26015:6;26007;25978:44;:::i;:::-;25970:52;25563:465;-1:-1:-1;;;;;25563:465:48:o;26033:401::-;26235:2;26217:21;;;26274:2;26254:18;;;26247:30;26313:34;26308:2;26293:18;;26286:62;-1:-1:-1;;;26379:2:48;26364:18;;26357:35;26424:3;26409:19;;26033:401::o;26439:406::-;26641:2;26623:21;;;26680:2;26660:18;;;26653:30;26719:34;26714:2;26699:18;;26692:62;-1:-1:-1;;;26785:2:48;26770:18;;26763:40;26835:3;26820:19;;26439:406::o;28964:407::-;29166:2;29148:21;;;29205:2;29185:18;;;29178:30;29244:34;29239:2;29224:18;;29217:62;-1:-1:-1;;;29310:2:48;29295:18;;29288:41;29361:3;29346:19;;28964:407::o;29376:827::-;-1:-1:-1;;;;;29773:15:48;;;29755:34;;29825:15;;29820:2;29805:18;;29798:43;29735:3;29872:2;29857:18;;29850:31;;;29698:4;;29904:57;;29941:19;;29933:6;29904:57;:::i;:::-;30009:9;30001:6;29997:22;29992:2;29981:9;29977:18;29970:50;30043:44;30080:6;30072;30043:44;:::i;:::-;30029:58;;30136:9;30128:6;30124:22;30118:3;30107:9;30103:19;30096:51;30164:33;30190:6;30182;30164:33;:::i;:::-;30156:41;29376:827;-1:-1:-1;;;;;;;;29376:827:48:o;30208:249::-;30277:6;30330:2;30318:9;30309:7;30305:23;30301:32;30298:52;;;30346:1;30343;30336:12;30298:52;30378:9;30372:16;30397:30;30421:5;30397:30;:::i;30462:179::-;30497:3;30539:1;30521:16;30518:23;30515:120;;;30585:1;30582;30579;30564:23;-1:-1:-1;30622:1:48;30616:8;30611:3;30607:18;30462:179;:::o;30646:671::-;30685:3;30727:4;30709:16;30706:26;30703:39;;;30646:671;:::o;30703:39::-;30769:2;30763:9;-1:-1:-1;;30834:16:48;30830:25;;30827:1;30763:9;30806:50;30885:4;30879:11;30909:16;-1:-1:-1;;;;;31015:2:48;31008:4;31000:6;30996:17;30993:25;30988:2;30980:6;30977:14;30974:45;30971:58;;;31022:5;;;;;30646:671;:::o;30971:58::-;31059:6;31053:4;31049:17;31038:28;;31095:3;31089:10;31122:2;31114:6;31111:14;31108:27;;;31128:5;;;;;;30646:671;:::o;31108:27::-;31212:2;31193:16;31187:4;31183:27;31179:36;31172:4;31163:6;31158:3;31154:16;31150:27;31147:69;31144:82;;;31219:5;;;;;;30646:671;:::o;31144:82::-;31235:57;31286:4;31277:6;31269;31265:19;31261:30;31255:4;31235:57;:::i;:::-;-1:-1:-1;31308:3:48;;30646:671;-1:-1:-1;;;;;30646:671:48:o;31743:404::-;31945:2;31927:21;;;31984:2;31964:18;;;31957:30;32023:34;32018:2;32003:18;;31996:62;-1:-1:-1;;;32089:2:48;32074:18;;32067:38;32137:3;32122:19;;31743:404::o;32501:561::-;-1:-1:-1;;;;;32798:15:48;;;32780:34;;32850:15;;32845:2;32830:18;;32823:43;32897:2;32882:18;;32875:34;;;32940:2;32925:18;;32918:34;;;32760:3;32983;32968:19;;32961:32;;;32723:4;;33010:46;;33036:19;;33028:6;33010:46;:::i;:::-;33002:54;32501:561;-1:-1:-1;;;;;;;32501:561:48:o;33464:127::-;33525:10;33520:3;33516:20;33513:1;33506:31;33556:4;33553:1;33546:15;33580:4;33577:1;33570:15
Swarm Source
ipfs://da2feff0257b5280c1fa25b0b334cebacd33e1db30d5b1a815a5de2a10c154a0
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
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.