Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PostOffice
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPLv3
pragma solidity 0.8.15;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "./access/Governable.sol";
import "./interfaces/ICapsule.sol";
import "./interfaces/ICapsuleMinter.sol";
import "./interfaces/ICapsuleProxy.sol";
error AddressIsNull();
error CallerIsNotAssetKeyHolder();
error CallerIsNotAssetKeyOwner();
error NotAuthorized();
error NotReceiver();
error ReceiverIsMissing();
error RedeemNotEnabled();
error ShippingNotEnabled();
error PackageHasBeenDelivered();
error PackageIsStillLocked();
error PasswordIsMissing();
error PasswordMismatched();
error UnsupportedCapsuleType();
abstract contract PostOfficeStorage is Governable, ReentrancyGuardUpgradeable, PausableUpgradeable {
enum PackageStatus {
NO_STATUS,
SHIPPED,
CANCELLED,
DELIVERED,
REDEEMED
}
/// @notice This struct holds info related to package security.
struct SecurityInfo {
bytes32 passwordHash; // Encoded hash of password and salt. keccak(encode(password, salt)).
uint64 unlockTimestamp; // Unix timestamp when package will be unlocked and ready to accept.
address keyAddress; // NFT collection address. If set receiver must hold at least 1 NFT in this collection.
uint256 keyId; // If keyAddress is set and keyId is set then receiver must hold keyId in order to accept package.
}
/// @notice This struct holds all info related to a package.
struct PackageInfo {
PackageStatus packageStatus; // Package Status
CapsuleData.CapsuleType capsuleType; // Type of Capsule
address manager; // Package Manager
address receiver; // Package receiver
SecurityInfo securityInfo; // Package security details
}
/// @notice Capsule Minter
ICapsuleMinter public capsuleMinter;
/// @notice Capsule Packaging collection
ICapsule public packagingCollection;
/// @notice CapsuleProxy. It does all the heavy lifting of minting/burning of Capsule.
address public capsuleProxy;
/// @notice Holds info of package. packageId => PackageInfo.
mapping(uint256 => PackageInfo) public packageInfo;
}
/**
* @title Capsule Post Office
* @author Capsule team
* @notice Capsule Post Office allows to ship packages, cancel packages, deliver packages and accept package.
* We have added security measures in place so that as a shipper you do not have to worry about what happen
* if you ship to wrong address? You can always update shipment or even cancel it altogether.
*
* You can ship package containing ERC20/ERC721/ERC1155 tokens to any recipient you provide.
* You are the shipper and you control how shipping will work.
* You get to choose
* - What to ship? An Empty Capsule, Capsule containing ERC20 or ERC721 or ERC1155 tokens.
* - Who to ship? Designated recipient or up for anyone to claim if recipient is address(0)
* - How to secure package? See security info of shipPackage().
* - How to make sure right recipient gets package? See security info of shipPackage().
* - Cancel the package. Yep you can do that anytime unless it is delivered.
* - Deliver the package yourself to recipient. :)
*/
contract PostOffice is PostOfficeStorage {
using SafeERC20Upgradeable for IERC20Upgradeable;
error WrongPackageStatus(PackageStatus);
/// @notice Current version of PostOffice
string public constant VERSION = "1.0.0";
event PackageShipped(uint256 indexed packageId, address indexed sender, address indexed receiver);
event PackageCancelled(uint256 indexed packageId, address indexed receiver);
event PackageDelivered(uint256 indexed packageId, address indexed receiver);
event PackageRedeemed(uint256 indexed packageId, address indexed burnFrom, address indexed receiver);
event PackageManagerUpdated(
uint256 indexed packageId,
address indexed oldPackageManager,
address indexed newPackageManager
);
event PackageReceiverUpdated(uint256 indexed packageId, address indexed oldReceiver, address indexed newReceiver);
event PackagePasswordHashUpdated(uint256 indexed packageId, bytes32 passwordHash);
event PackageAssetKeyUpdated(uint256 indexed packageId, address indexed keyAddress, uint256 keyId);
event PackageUnlockTimestampUpdated(uint256 indexed packageId, uint256 unlockTimestamp);
constructor() {
_disableInitializers();
}
function initialize(
ICapsuleMinter capsuleMinter_,
ICapsule capsuleCollection_,
address capsuleProxy_
) external initializer {
if (address(capsuleMinter_) == address(0)) revert AddressIsNull();
if (address(capsuleCollection_) == address(0)) revert AddressIsNull();
if (capsuleProxy_ == address(0)) revert AddressIsNull();
capsuleMinter = capsuleMinter_;
packagingCollection = capsuleCollection_;
capsuleProxy = capsuleProxy_;
__Governable_init();
__Pausable_init();
__ReentrancyGuard_init();
// Deploy PostOffice in paused state
_pause();
}
/**
* @notice Ship package containing ERC20/ERC721/ERC1155 tokens to any recipient you provide.
* @param packageContent_ Contents of package to ship. A Capsule will be created using these contents.
* This param is struct of `CapsuleData.CapsuleContent` type.
* enum CapsuleType { SIMPLE, ERC20, ERC721, ERC1155 }
* struct CapsuleContent {
* CapsuleType capsuleType; // Capsule Type from above enum
* address[] tokenAddresses; // Tokens to send in packages
* uint256[] tokenIds; // TokenIds in case of ERC721 and ERC1155. Send 0 for ERC20.
* uint256[] amounts; // Token amounts in case of ERC20 and ERC1155. Send 0 for ERC721.
* string tokenURI; // TokenURI for Capsule NFT
* }
*
* @param securityInfo_ It is important to deliver package to right receiver and hence package security
* comes into picture. It is possible to secure your package and there are 3 independent security measures are supported.
* For any given package you can provide none, all or any combination of these 3.
* 1. Password lock. `receiver_` will have to provide a password to accept package.
* 2. Time lock, `receiver_` can not accept before time lock is unlocked.
* 3. AssetKey lock. `receiver_` must be hold at least 1 NFT in NFT collection at `keyAddress`.
* `receiver_` must hold NFT with specific id from NFT collection if `keyId` is set.
* If do not want to enforce `keyId` then provider type(uint256).max as `keyId`.
*
* struct SecurityInfo {
* bytes32 passwordHash; // Encoded hash of password and salt. keccak(encode(password, salt))
* // `receiver` will need password and salt both to accept package.
* uint64 unlockTimestamp; // Unix timestamp when package will be unlocked and ready to accept
* address keyAddress; // NFT collection address. If set receiver must hold at least 1 NFT in this collection.
* uint256 keyId; // If keyAddress is set and keyId is set then receiver must hold keyId in order to accept package.
* }
*
* @param receiver_ Package receiver. `receiver_` can be zero if you want address to accept/claim this package.
*/
function shipPackage(
CapsuleData.CapsuleContent calldata packageContent_,
SecurityInfo calldata securityInfo_,
address receiver_
) external payable whenNotPaused nonReentrant returns (uint256 _packageId) {
// Mint capsule based on contains of package
_packageId = _executeViaProxy(
abi.encodeWithSelector(
ICapsuleProxy.mintCapsule.selector,
address(packagingCollection),
packageContent_,
address(this)
)
);
// Prepare package info for shipping
PackageInfo memory _pInfo = PackageInfo({
capsuleType: packageContent_.capsuleType,
packageStatus: PackageStatus.SHIPPED,
manager: msg.sender,
receiver: receiver_,
securityInfo: securityInfo_
});
// Store package info
packageInfo[_packageId] = _pInfo;
emit PackageShipped(_packageId, msg.sender, receiver_);
}
/**
* @notice Package receiver will call this function.
* This function will make sure caller and package state pass all the security measure before it get delivered.
* @param packageId_ Package id of Capsule package.
* @param rawPassword_ Plain text password. You get it from shipper. Send empty('') if no password lock.
* @param salt_ Plain text salt. You get it from shipper(unless you shipped via Capsule UI). Send empty('') if no password lock.
* @param redeemPackage_ Boolean flag indicating you want to wrap package or want it as is.
* True == You want to unwrap package aka burn Capsule NFT and get contents transferred to you.
* False == You want to receive Capsule NFT. You can always redeem/burn this NFT later and receive contents.
*/
function acceptPackage(
uint256 packageId_,
string calldata rawPassword_,
string calldata salt_,
bool redeemPackage_
) external payable whenNotPaused nonReentrant {
_validateShippedStatus(packageInfo[packageId_].packageStatus);
address _receiver = packageInfo[packageId_].receiver;
SecurityInfo memory _sInfo = packageInfo[packageId_].securityInfo;
address _caller = msg.sender;
if (_receiver == address(0)) {
_receiver = _caller;
packageInfo[packageId_].receiver = _caller;
} else if (_receiver != _caller) revert NotReceiver();
// Security Mode:: TIME_LOCKED
if (_sInfo.unlockTimestamp > block.timestamp) revert PackageIsStillLocked();
// Security Mode:: ASSET_KEY
if (_sInfo.keyAddress != address(0)) {
// If no specific id is provided then check if caller is holder
if (_sInfo.keyId == type(uint256).max) {
if (IERC721(_sInfo.keyAddress).balanceOf(msg.sender) == 0) revert CallerIsNotAssetKeyHolder();
} else {
// If specific id is provided then caller must be owner of keyId NFT collection
if (IERC721(_sInfo.keyAddress).ownerOf(_sInfo.keyId) != msg.sender) revert CallerIsNotAssetKeyOwner();
}
}
// Security Mode:: PASSWORD_PROTECTED
if (_sInfo.passwordHash != bytes32(0)) {
if (_getPasswordHash(rawPassword_, salt_) != _sInfo.passwordHash) revert PasswordMismatched();
}
if (redeemPackage_) {
emit PackageDelivered(packageId_, _receiver);
_redeemPackage(packageId_, address(this), _receiver);
} else {
_deliverPackage(packageId_, _receiver);
}
}
/**
* @notice Redeem package by unwrapping package(burning Capsule). Package contents will be transferred to `receiver_`.
* There are 2 cases when you have wrapped package,
* 1. Package got delivered to you.
* 2. You(recipient) accepted package at PostOffice without redeeming it.
* In above cases you have a Capsule NFT, you can redeem this NFT for it's content using this function.
* @param packageId_ Package id
* @param receiver_ receive of package/Capsule contents.
*/
function redeemPackage(uint256 packageId_, address receiver_) external whenNotPaused nonReentrant {
if (receiver_ == address(0)) revert AddressIsNull();
PackageStatus _status = packageInfo[packageId_].packageStatus;
if (_status != PackageStatus.DELIVERED) revert WrongPackageStatus(_status);
// It is quite possible that after delivery of package, original receiver transfer package to someone else.
// Hence we will redeem package to provided receiver_ address and not on receiver stored in packageInfo
_redeemPackage(packageId_, msg.sender, receiver_);
}
/**
* @notice Get security info of package
* @param packageId_ Package Id
*/
function securityInfo(uint256 packageId_) external view returns (SecurityInfo memory) {
return packageInfo[packageId_].securityInfo;
}
function _burnCapsule(
CapsuleData.CapsuleType capsuleType_,
uint256 packageId_,
address burnFrom_,
address receiver_
) internal {
_executeViaProxy(
abi.encodeWithSelector(
ICapsuleProxy.burnCapsule.selector,
address(packagingCollection),
capsuleType_,
packageId_,
burnFrom_,
receiver_
)
);
}
function _checkPackageInfo(uint256 packageId_) private view {
if (msg.sender != packageInfo[packageId_].manager && msg.sender != governor) revert NotAuthorized();
_validateShippedStatus(packageInfo[packageId_].packageStatus);
}
function _deliverPackage(uint256 packageId_, address receiver_) internal {
packageInfo[packageId_].packageStatus = PackageStatus.DELIVERED;
packagingCollection.safeTransferFrom(address(this), receiver_, packageId_);
emit PackageDelivered(packageId_, receiver_);
}
function _executeViaProxy(bytes memory _data) private returns (uint256) {
// solhint-disable-next-line avoid-low-level-calls
(bool _success, bytes memory _returnData) = capsuleProxy.delegatecall(_data);
if (_success) {
return _returnData.length > 0 ? abi.decode(_returnData, (uint256)) : 0;
} else {
// Below code is taken from https://ethereum.stackexchange.com/a/114140
// solhint-disable-next-line no-inline-assembly
assembly {
revert(add(_returnData, 32), _returnData)
}
}
}
function _getPasswordHash(string calldata inputPassword_, string calldata salt_) internal pure returns (bytes32) {
return keccak256(abi.encode(inputPassword_, salt_));
}
function _redeemPackage(uint256 packageId_, address burnFrom_, address receiver_) internal {
packageInfo[packageId_].packageStatus = PackageStatus.REDEEMED;
_burnCapsule(packageInfo[packageId_].capsuleType, packageId_, burnFrom_, receiver_);
emit PackageRedeemed(packageId_, burnFrom_, receiver_);
}
function _validateShippedStatus(PackageStatus _status) internal pure {
if (_status != PackageStatus.SHIPPED) revert WrongPackageStatus(_status);
}
/******************************************************************************
* Package Manager & Governor functions *
*****************************************************************************/
/**
* @notice onlyPackageManager:: Cancel package aka cancel package/shipment
* @param packageId_ id of package to cancel
* @param contentReceiver_ Address which will receive contents of package
*/
function cancelPackage(uint256 packageId_, address contentReceiver_) external whenNotPaused nonReentrant {
if (contentReceiver_ == address(0)) revert AddressIsNull();
_checkPackageInfo(packageId_);
packageInfo[packageId_].packageStatus = PackageStatus.CANCELLED;
_burnCapsule(packageInfo[packageId_].capsuleType, packageId_, address(this), contentReceiver_);
emit PackageCancelled(packageId_, contentReceiver_);
}
/**
* @notice onlyPackageManager:: Deliver package to receiver
* @param packageId_ id of package to deliver
*/
function deliverPackage(uint packageId_) external whenNotPaused nonReentrant {
address _receiver = packageInfo[packageId_].receiver;
if (_receiver == address(0)) revert ReceiverIsMissing();
_checkPackageInfo(packageId_);
// All security measures are bypassed. It is better to set unlockTimestamp for consistency.
if (packageInfo[packageId_].securityInfo.unlockTimestamp > uint64(block.timestamp)) {
packageInfo[packageId_].securityInfo.unlockTimestamp = uint64(block.timestamp);
}
_deliverPackage(packageId_, _receiver);
}
/**
* @notice onlyPackageManager:: Update AssetKey of package
* @param packageId_ PackageId
* @param newKeyAddress_ AssetKey address aka ERC721 collection address
* @param newKeyId_ AssetKey id aka NFT id
*/
function updatePackageAssetKey(
uint256 packageId_,
address newKeyAddress_,
uint256 newKeyId_
) external whenNotPaused {
_checkPackageInfo(packageId_);
emit PackageAssetKeyUpdated(packageId_, newKeyAddress_, newKeyId_);
packageInfo[packageId_].securityInfo.keyAddress = newKeyAddress_;
packageInfo[packageId_].securityInfo.keyId = newKeyId_;
}
/**
* @notice onlyPackageManager:: Update PackageManger of package
* @param packageId_ PackageId
* @param newPackageManager_ New PackageManager address
*/
function updatePackageManager(uint256 packageId_, address newPackageManager_) external whenNotPaused {
if (newPackageManager_ == address(0)) revert AddressIsNull();
_checkPackageInfo(packageId_);
emit PackageManagerUpdated(packageId_, packageInfo[packageId_].manager, newPackageManager_);
packageInfo[packageId_].manager = newPackageManager_;
}
/**
* @notice onlyPackageManager:: Update PasswordHash of package
* @param packageId_ PackageId
* @param newPasswordHash_ New password hash
*/
function updatePackagePasswordHash(uint256 packageId_, bytes32 newPasswordHash_) external whenNotPaused {
_checkPackageInfo(packageId_);
emit PackagePasswordHashUpdated(packageId_, newPasswordHash_);
packageInfo[packageId_].securityInfo.passwordHash = newPasswordHash_;
}
/**
* @notice onlyPackageManager:: Update package receiver
* @param packageId_ PackageId
* @param newReceiver_ New receiver address
*/
function updatePackageReceiver(uint256 packageId_, address newReceiver_) external whenNotPaused {
_checkPackageInfo(packageId_);
emit PackageReceiverUpdated(packageId_, packageInfo[packageId_].receiver, newReceiver_);
packageInfo[packageId_].receiver = newReceiver_;
}
/**
* @notice onlyPackageManager:: Update package unlock timestamp
* @param packageId_ PackageId
* @param newUnlockTimestamp_ New unlock timestamp
*/
function updatePackageUnlockTimestamp(uint256 packageId_, uint64 newUnlockTimestamp_) external whenNotPaused {
_checkPackageInfo(packageId_);
emit PackageUnlockTimestampUpdated(packageId_, newUnlockTimestamp_);
packageInfo[packageId_].securityInfo.unlockTimestamp = newUnlockTimestamp_;
}
/******************************************************************************
* Governor functions *
*****************************************************************************/
/**
* @notice onlyGovernor:: Triggers stopped state.
*
* Requirements:
* - The contract must not be paused.
*/
function pause() external onlyGovernor {
_pause();
}
/// @notice onlyGovernor:: Sweep given token to governor address
function sweep(address _token) external onlyGovernor {
if (_token == address(0)) {
AddressUpgradeable.sendValue(payable(governor), address(this).balance);
} else {
uint256 _amount = IERC20Upgradeable(_token).balanceOf(address(this));
IERC20Upgradeable(_token).safeTransfer(governor, _amount);
}
}
/**
* @notice onlyGovernor:: Transfer ownership of the packaging collection
* @param newOwner_ Address of new owner
*/
function transferCollectionOwnership(address newOwner_) external onlyGovernor {
packagingCollection.transferOwnership(newOwner_);
}
/**
* @notice onlyGovernor:: Returns to normal state.
*
* Requirements:
* - The contract must be paused.
*/
function unpause() external onlyGovernor {
_unpause();
}
/**
* @notice onlyGovernor:: Set the collection baseURI
* @param baseURI_ New baseURI string
*/
function updateBaseURI(string memory baseURI_) public onlyGovernor {
packagingCollection.setBaseURI(baseURI_);
}
/**
* @notice onlyGovernor:: Set collection burner address
* @param _newBurner Address of collection burner
*/
function updateCollectionBurner(address _newBurner) external onlyGovernor {
capsuleMinter.factory().updateCapsuleCollectionBurner(address(packagingCollection), _newBurner);
}
/**
* @notice onlyGovernor:: Transfer metamaster of the packaging collection
* @param metamaster_ Address of new metamaster
*/
function updateMetamaster(address metamaster_) external onlyGovernor {
packagingCollection.updateTokenURIOwner(metamaster_);
}
/**
* @notice onlyGovernor:: Update royalty receiver and rate in packaging collection
* @param royaltyReceiver_ Address of royalty receiver
* @param royaltyRate_ Royalty rate in Basis Points. ie. 100 = 1%, 10_000 = 100%
*/
function updateRoyaltyConfig(address royaltyReceiver_, uint256 royaltyRate_) external onlyGovernor {
packagingCollection.updateRoyaltyConfig(royaltyReceiver_, royaltyRate_);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (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.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
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.
*
* 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.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* 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.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
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.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// 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 (last updated v4.8.0) (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() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// 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 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 IERC20PermitUpgradeable {
/**
* @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 (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 IERC20Upgradeable {
/**
* @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.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../extensions/draft-IERC20PermitUpgradeable.sol";
import "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20Upgradeable 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(
IERC20Upgradeable 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(
IERC20Upgradeable 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(
IERC20Upgradeable 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(
IERC20PermitUpgradeable 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(IERC20Upgradeable 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.8.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 functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
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 (last updated v4.6.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// 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
pragma solidity 0.8.15;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "../interfaces/IGovernable.sol";
error CallerIsNotGovernor();
error ProposedGovernorIsNull();
error CallerIsNotTheProposedGovernor();
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (governor) that can be granted exclusive access to
* specific functions.
*
* By default, the governor account will be the one that deploys the contract. This
* can later be changed with {transferGovernorship}.
*
*/
abstract contract Governable is IGovernable, ContextUpgradeable {
address public governor;
address private proposedGovernor;
event UpdatedGovernor(address indexed previousGovernor, address indexed proposedGovernor);
/**
* @dev Initializes the contract setting the deployer as the initial governor.
*/
constructor() {
address msgSender = _msgSender();
governor = msgSender;
emit UpdatedGovernor(address(0), msgSender);
}
/**
* @dev Initializes the contract setting the deployer as the initial governor.
*/
// solhint-disable-next-line func-name-mixedcase
function __Governable_init() internal onlyInitializing {
address msgSender = _msgSender();
governor = msgSender;
emit UpdatedGovernor(address(0), msgSender);
}
/**
* @dev Throws if called by any account other than the governor.
*/
modifier onlyGovernor() {
if (governor != msg.sender) revert CallerIsNotGovernor();
_;
}
/**
* @dev Transfers governorship of the contract to a new account (`proposedGovernor`).
* Can only be called by the current governor.
*/
function transferGovernorship(address proposedGovernor_) external onlyGovernor {
if (proposedGovernor_ == address(0)) revert ProposedGovernorIsNull();
proposedGovernor = proposedGovernor_;
}
/**
* @dev Allows new governor to accept governorship of the contract.
*/
function acceptGovernorship() external {
address _proposedGovernor = proposedGovernor;
if (msg.sender != _proposedGovernor) revert CallerIsNotTheProposedGovernor();
emit UpdatedGovernor(governor, _proposedGovernor);
governor = _proposedGovernor;
proposedGovernor = address(0);
}
/**
* @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
pragma solidity 0.8.15;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
interface ICapsule is IERC721, IERC2981 {
function mint(address account, string memory _uri) external;
function burn(address owner, uint256 tokenId) external;
function setMetadataProvider(address _metadataAddress) external;
// Read functions
function baseURI() external view returns (string memory);
function counter() external view returns (uint256);
function exists(uint256 tokenId) external view returns (bool);
function isCollectionMinter(address _account) external view returns (bool);
function isCollectionPrivate() external view returns (bool);
function maxId() external view returns (uint256);
function royaltyRate() external view returns (uint256);
function royaltyReceiver() external view returns (address);
function tokenURIOwner() external view returns (address);
////////////////////////////////////////////////////////////////////////////
// Extra functions compare to original ICapsule interface ///////////
////////////////////////////////////////////////////////////////////////////
// Read functions
function owner() external view returns (address);
function tokenURI(uint256 tokenId) external view returns (string memory);
// Admin functions
function lockCollectionCount(uint256 _nftCount) external;
function setBaseURI(string calldata baseURI_) external;
function setTokenURI(uint256 _tokenId, string memory _newTokenURI) external;
function transferOwnership(address _newOwner) external;
function updateTokenURIOwner(address _newTokenURIOwner) external;
function updateRoyaltyConfig(address _royaltyReceiver, uint256 _royaltyRate) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import "./IGovernable.sol";
interface ICapsuleFactory is IGovernable {
function capsuleCollectionTax() external view returns (uint256);
function capsuleMinter() external view returns (address);
function createCapsuleCollection(
string memory _name,
string memory _symbol,
address _tokenURIOwner,
bool _isCollectionPrivate
) external payable returns (address);
function collectionBurner(address _capsule) external view returns (address);
function getAllCapsuleCollections() external view returns (address[] memory);
function getCapsuleCollectionsOf(address _owner) external view returns (address[] memory);
function getBlacklist() external view returns (address[] memory);
function getWhitelist() external view returns (address[] memory);
function isBlacklisted(address _user) external view returns (bool);
function isCapsule(address _capsule) external view returns (bool);
function isCollectionBurner(address _capsuleCollection, address _account) external view returns (bool);
function isWhitelisted(address _user) external view returns (bool);
function taxCollector() external view returns (address);
//solhint-disable-next-line func-name-mixedcase
function VERSION() external view returns (string memory);
// Special permission functions
function addToWhitelist(address _user) external;
function removeFromWhitelist(address _user) external;
function addToBlacklist(address _user) external;
function removeFromBlacklist(address _user) external;
function flushTaxAmount() external;
function setCapsuleMinter(address _newCapsuleMinter) external;
function updateCapsuleCollectionBurner(address _capsuleCollection, address _newBurner) external;
function updateCapsuleCollectionOwner(address _previousOwner, address _newOwner) external;
function updateCapsuleCollectionTax(uint256 _newTax) external;
function updateTaxCollector(address _newTaxCollector) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import "./IGovernable.sol";
import "./ICapsuleFactory.sol";
interface ICapsuleMinter is IGovernable {
struct SingleERC20Capsule {
address tokenAddress;
uint256 tokenAmount;
}
struct MultiERC20Capsule {
address[] tokenAddresses;
uint256[] tokenAmounts;
}
struct SingleERC721Capsule {
address tokenAddress;
uint256 id;
}
struct MultiERC721Capsule {
address[] tokenAddresses;
uint256[] ids;
}
struct MultiERC1155Capsule {
address[] tokenAddresses;
uint256[] ids;
uint256[] tokenAmounts;
}
function capsuleMintTax() external view returns (uint256);
function factory() external view returns (ICapsuleFactory);
function getMintWhitelist() external view returns (address[] memory);
function getCapsuleOwner(address _capsule, uint256 _id) external view returns (address);
function getWhitelistedCallers() external view returns (address[] memory);
function isMintWhitelisted(address _user) external view returns (bool);
function isWhitelistedCaller(address _caller) external view returns (bool);
function multiERC20Capsule(address _capsule, uint256 _id) external view returns (MultiERC20Capsule memory _data);
function multiERC721Capsule(address _capsule, uint256 _id) external view returns (MultiERC721Capsule memory _data);
function multiERC1155Capsule(
address _capsule,
uint256 _id
) external view returns (MultiERC1155Capsule memory _data);
function singleERC20Capsule(address _capsule, uint256 _id) external view returns (SingleERC20Capsule memory);
function singleERC721Capsule(address _capsule, uint256 _id) external view returns (SingleERC721Capsule memory);
function mintSimpleCapsule(address _capsule, string memory _uri, address _receiver) external payable;
function burnSimpleCapsule(address _capsule, uint256 _id, address _burnFrom) external;
function mintSingleERC20Capsule(
address _capsule,
address _token,
uint256 _amount,
string memory _uri,
address _receiver
) external payable;
function burnSingleERC20Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external;
function mintSingleERC721Capsule(
address _capsule,
address _token,
uint256 _id,
string memory _uri,
address _receiver
) external payable;
function burnSingleERC721Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external;
function mintMultiERC20Capsule(
address _capsule,
address[] memory _tokens,
uint256[] memory _amounts,
string memory _uri,
address _receiver
) external payable;
function burnMultiERC20Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external;
function mintMultiERC721Capsule(
address _capsule,
address[] memory _tokens,
uint256[] memory _ids,
string memory _uri,
address _receiver
) external payable;
function burnMultiERC721Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external;
function mintMultiERC1155Capsule(
address _capsule,
address[] memory _tokens,
uint256[] memory _ids,
uint256[] memory _amounts,
string memory _uri,
address _receiver
) external payable;
function burnMultiERC1155Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external;
// Special permission functions
function addToWhitelist(address _user) external;
function removeFromWhitelist(address _user) external;
function flushTaxAmount() external;
function updateCapsuleMintTax(uint256 _newTax) external;
function updateWhitelistedCallers(address _caller) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
interface CapsuleData {
enum CapsuleType {
SIMPLE,
ERC20,
ERC721,
ERC1155
}
struct CapsuleContent {
CapsuleType capsuleType;
address[] tokenAddresses;
uint256[] tokenIds;
uint256[] amounts;
string tokenURI;
}
}
interface ICapsuleProxy {
function burnCapsule(
address collection_,
CapsuleData.CapsuleType capsuleType_,
uint256 capsuleId_,
address burnFrom_,
address receiver_
) external;
function mintCapsule(
address collection_,
CapsuleData.CapsuleContent calldata capsuleContent_,
address receiver_
) external payable returns (uint256 _capsuleId);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
* @notice Governable interface
*/
interface IGovernable {
function governor() external view returns (address _governor);
function transferGovernorship(address _proposedGovernor) external;
}{
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressIsNull","type":"error"},{"inputs":[],"name":"CallerIsNotAssetKeyHolder","type":"error"},{"inputs":[],"name":"CallerIsNotAssetKeyOwner","type":"error"},{"inputs":[],"name":"CallerIsNotGovernor","type":"error"},{"inputs":[],"name":"CallerIsNotTheProposedGovernor","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotReceiver","type":"error"},{"inputs":[],"name":"PackageIsStillLocked","type":"error"},{"inputs":[],"name":"PasswordMismatched","type":"error"},{"inputs":[],"name":"ProposedGovernorIsNull","type":"error"},{"inputs":[],"name":"ReceiverIsMissing","type":"error"},{"inputs":[{"internalType":"enum PostOfficeStorage.PackageStatus","name":"","type":"uint8"}],"name":"WrongPackageStatus","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"keyAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"keyId","type":"uint256"}],"name":"PackageAssetKeyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"PackageCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"PackageDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldPackageManager","type":"address"},{"indexed":true,"internalType":"address","name":"newPackageManager","type":"address"}],"name":"PackageManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"passwordHash","type":"bytes32"}],"name":"PackagePasswordHashUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldReceiver","type":"address"},{"indexed":true,"internalType":"address","name":"newReceiver","type":"address"}],"name":"PackageReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"burnFrom","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"PackageRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"PackageShipped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"packageId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTimestamp","type":"uint256"}],"name":"PackageUnlockTimestampUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"proposedGovernor","type":"address"}],"name":"UpdatedGovernor","type":"event"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"string","name":"rawPassword_","type":"string"},{"internalType":"string","name":"salt_","type":"string"},{"internalType":"bool","name":"redeemPackage_","type":"bool"}],"name":"acceptPackage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"address","name":"contentReceiver_","type":"address"}],"name":"cancelPackage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"capsuleMinter","outputs":[{"internalType":"contract ICapsuleMinter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"capsuleProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"}],"name":"deliverPackage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ICapsuleMinter","name":"capsuleMinter_","type":"address"},{"internalType":"contract ICapsule","name":"capsuleCollection_","type":"address"},{"internalType":"address","name":"capsuleProxy_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"packageInfo","outputs":[{"internalType":"enum PostOfficeStorage.PackageStatus","name":"packageStatus","type":"uint8"},{"internalType":"enum CapsuleData.CapsuleType","name":"capsuleType","type":"uint8"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"components":[{"internalType":"bytes32","name":"passwordHash","type":"bytes32"},{"internalType":"uint64","name":"unlockTimestamp","type":"uint64"},{"internalType":"address","name":"keyAddress","type":"address"},{"internalType":"uint256","name":"keyId","type":"uint256"}],"internalType":"struct PostOfficeStorage.SecurityInfo","name":"securityInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"packagingCollection","outputs":[{"internalType":"contract ICapsule","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":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"address","name":"receiver_","type":"address"}],"name":"redeemPackage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"}],"name":"securityInfo","outputs":[{"components":[{"internalType":"bytes32","name":"passwordHash","type":"bytes32"},{"internalType":"uint64","name":"unlockTimestamp","type":"uint64"},{"internalType":"address","name":"keyAddress","type":"address"},{"internalType":"uint256","name":"keyId","type":"uint256"}],"internalType":"struct PostOfficeStorage.SecurityInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum CapsuleData.CapsuleType","name":"capsuleType","type":"uint8"},{"internalType":"address[]","name":"tokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"string","name":"tokenURI","type":"string"}],"internalType":"struct CapsuleData.CapsuleContent","name":"packageContent_","type":"tuple"},{"components":[{"internalType":"bytes32","name":"passwordHash","type":"bytes32"},{"internalType":"uint64","name":"unlockTimestamp","type":"uint64"},{"internalType":"address","name":"keyAddress","type":"address"},{"internalType":"uint256","name":"keyId","type":"uint256"}],"internalType":"struct PostOfficeStorage.SecurityInfo","name":"securityInfo_","type":"tuple"},{"internalType":"address","name":"receiver_","type":"address"}],"name":"shipPackage","outputs":[{"internalType":"uint256","name":"_packageId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferCollectionOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proposedGovernor_","type":"address"}],"name":"transferGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"updateBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newBurner","type":"address"}],"name":"updateCollectionBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metamaster_","type":"address"}],"name":"updateMetamaster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"address","name":"newKeyAddress_","type":"address"},{"internalType":"uint256","name":"newKeyId_","type":"uint256"}],"name":"updatePackageAssetKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"address","name":"newPackageManager_","type":"address"}],"name":"updatePackageManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"bytes32","name":"newPasswordHash_","type":"bytes32"}],"name":"updatePackagePasswordHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"address","name":"newReceiver_","type":"address"}],"name":"updatePackageReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packageId_","type":"uint256"},{"internalType":"uint64","name":"newUnlockTimestamp_","type":"uint64"}],"name":"updatePackageUnlockTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"royaltyReceiver_","type":"address"},{"internalType":"uint256","name":"royaltyRate_","type":"uint256"}],"name":"updateRoyaltyConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50600062000024620000d960201b60201c565b905080603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d060405160405180910390a350620000d3620000e160201b60201c565b6200028c565b600033905090565b600060019054906101000a900460ff161562000134576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200012b906200022f565b60405180910390fd5b60ff801660008054906101000a900460ff1660ff161015620001a65760ff6000806101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff6040516200019d91906200026f565b60405180910390a15b565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b600062000217602783620001a8565b91506200022482620001b9565b604082019050919050565b600060208201905081810360008301526200024a8162000208565b9050919050565b600060ff82169050919050565b620002698162000251565b82525050565b60006020820190506200028660008301846200025e565b92915050565b614f28806200029c6000396000f3fe6080604052600436106101c25760003560e01c806370cf0f62116100f7578063b61aee8f11610095578063f07a72a511610064578063f07a72a5146105d4578063f3b27bc3146105fd578063fce1264414610614578063ffa1ad741461063d576101c2565b8063b61aee8f14610511578063b6aa515b14610552578063b8ecac0f1461057b578063c0c53b8b146105ab576101c2565b80638d5cdc26116100d15780638d5cdc2614610459578063931688cb146104825780639fd12003146104ab578063a4e04687146104e8576101c2565b806370cf0f62146103ee57806376a90fd6146104195780638456cb5914610442576101c2565b80633f4ba83a116101645780635a9093f71161013e5780635a9093f7146103535780635c975abb1461037c57806366e65b04146103a75780636a5fd500146103d2576101c2565b80633f4ba83a146102e8578063487aac87146102ff5780634c0cc9ad14610328576101c2565b806306d4cc4e116101a057806306d4cc4e146102425780630c340a241461026b57806312150b5d1461029657806334f74482146102bf576101c2565b806301681a62146101c757806303c5a604146101f057806304dad93514610219575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e991906136fe565b610668565b005b3480156101fc57600080fd5b50610217600480360381019061021291906136fe565b610824565b005b34801561022557600080fd5b50610240600480360381019061023b91906136fe565b6109cd565b005b34801561024e57600080fd5b5061026960048036038101906102649190613761565b610ae4565b005b34801561027757600080fd5b50610280610bdf565b60405161028d91906137b0565b60405180910390f35b3480156102a257600080fd5b506102bd60048036038101906102b891906137cb565b610c05565b005b3480156102cb57600080fd5b506102e660048036038101906102e19190613838565b610d5f565b005b3480156102f457600080fd5b506102fd610dec565b005b34801561030b57600080fd5b5061032660048036038101906103219190613761565b610e7d565b005b34801561033457600080fd5b5061033d610f9c565b60405161034a91906138d7565b60405180910390f35b34801561035f57600080fd5b5061037a60048036038101906103759190613761565b610fc2565b005b34801561038857600080fd5b50610391611123565b60405161039e919061390d565b60405180910390f35b3480156103b357600080fd5b506103bc61113a565b6040516103c99190613949565b60405180910390f35b6103ec60048036038101906103e791906139f5565b611160565b005b3480156103fa57600080fd5b506104036116b2565b60405161041091906137b0565b60405180910390f35b34801561042557600080fd5b50610440600480360381019061043b9190613a9c565b6116d8565b005b34801561044e57600080fd5b506104576117b3565b005b34801561046557600080fd5b50610480600480360381019061047b9190613aef565b611844565b005b34801561048e57600080fd5b506104a960048036038101906104a49190613c70565b61195e565b005b3480156104b757600080fd5b506104d260048036038101906104cd91906137cb565b611a75565b6040516104df9190613d54565b60405180910390f35b3480156104f457600080fd5b5061050f600480360381019061050a9190613d9b565b611b41565b005b34801561051d57600080fd5b50610538600480360381019061053391906137cb565b611bac565b604051610549959493929190613e9a565b60405180910390f35b34801561055e57600080fd5b50610579600480360381019061057491906136fe565b611ce2565b005b61059560048036038101906105909190613f31565b611e13565b6040516105a29190613faf565b60405180910390f35b3480156105b757600080fd5b506105d260048036038101906105cd9190614046565b61216e565b005b3480156105e057600080fd5b506105fb60048036038101906105f69190613761565b6124bc565b005b34801561060957600080fd5b506106126125f9565b005b34801561062057600080fd5b5061063b600480360381019061063691906136fe565b612787565b005b34801561064957600080fd5b5061065261289e565b60405161065f9190614121565b60405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106ef576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036107545761074f603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476128d7565b610821565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161078f91906137b0565b602060405180830381865afa1580156107ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d09190614158565b905061081f603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828473ffffffffffffffffffffffffffffffffffffffff166129cb9092919063ffffffff16565b505b50565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146108ab576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093c91906141c3565b73ffffffffffffffffffffffffffffffffffffffff166377394a0b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b81526004016109989291906141f0565b600060405180830381600087803b1580156109b257600080fd5b505af11580156109c6573d6000803e3d6000fd5b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a54576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b8152600401610aaf91906137b0565b600060405180830381600087803b158015610ac957600080fd5b505af1158015610add573d6000803e3d6000fd5b5050505050565b610aec612a51565b610af582612a9b565b8073ffffffffffffffffffffffffffffffffffffffff1660cd600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16837f88fe5eceecf1a4a3a6c64c2cf34b14369016f06ae9e9993dc74c3698908c32c260405160405180910390a48060cd600084815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c0d612a51565b610c15612bc1565b600060cd600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610cb6576040517f4834d46700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cbf82612a9b565b4267ffffffffffffffff1660cd600084815260200190815260200160002060020160010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff161115610d49574260cd600084815260200190815260200160002060020160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b610d538282612c10565b50610d5c612d28565b50565b610d67612a51565b610d7082612a9b565b817f20d5405556a3fe0f705a94a30df3ad62f7f464850bb85bb8f1761b437022564782604051610da0919061424a565b60405180910390a28060cd600084815260200190815260200160002060020160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e73576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e7b612d32565b565b610e85612a51565b610e8d612bc1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef3576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060cd600084815260200190815260200160002060000160009054906101000a900460ff16905060036004811115610f2f57610f2e613ddb565b5b816004811115610f4257610f41613ddb565b5b14610f8457806040517ff20f442d000000000000000000000000000000000000000000000000000000008152600401610f7b9190614265565b60405180910390fd5b610f8f833384612d95565b50610f98612d28565b5050565b60ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610fca612a51565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611030576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61103982612a9b565b8073ffffffffffffffffffffffffffffffffffffffff1660cd600084815260200190815260200160002060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16837feb1f466e88badaa63cbff09a15461e10f48e6ccd5c129744bce2c5c8a6da5b3d60405160405180910390a48060cd600084815260200190815260200160002060000160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000609860009054906101000a900460ff16905090565b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611168612a51565b611170612bc1565b61119c60cd600088815260200190815260200160002060000160009054906101000a900460ff16612e63565b600060cd600088815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600060cd6000898152602001908152602001600020600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152505090506000339050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132e578092508060cd60008b815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611394565b8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614611393576040517fb40c733e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b42826020015167ffffffffffffffff1611156113dc576040517f83aaa10700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16826040015173ffffffffffffffffffffffffffffffffffffffff16146115e3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260600151036114fb576000826040015173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b815260040161147e91906137b0565b602060405180830381865afa15801561149b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bf9190614158565b036114f6576040517fd988302600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115e2565b3373ffffffffffffffffffffffffffffffffffffffff16826040015173ffffffffffffffffffffffffffffffffffffffff16636352211e84606001516040518263ffffffff1660e01b81526004016115539190613faf565b602060405180830381865afa158015611570573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115949190614295565b73ffffffffffffffffffffffffffffffffffffffff16146115e1576040517fe113e38000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5b6000801b82600001511461163a57816000015161160289898989612ecf565b14611639576040517f1154ef1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8315611694578273ffffffffffffffffffffffffffffffffffffffff16897fdd940b4c0a591c09ff1b1398b5a2a336cb49f986e98a1f8d9fae939fe305be7c60405160405180910390a361168f893085612d95565b61169f565b61169e8984612c10565b5b5050506116aa612d28565b505050505050565b60cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6116e0612a51565b6116e983612a9b565b8173ffffffffffffffffffffffffffffffffffffffff16837fced9903a2507fd2340fce78cf61525e862723bdffda3179cc48f4aa0ec77ab25836040516117309190613faf565b60405180910390a38160cd600085815260200190815260200160002060020160010160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060cd600085815260200190815260200160002060020160020181905550505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461183a576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611842612f08565b565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146118cb576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638d5cdc2683836040518363ffffffff1660e01b81526004016119289291906142c2565b600060405180830381600087803b15801561194257600080fd5b505af1158015611956573d6000803e3d6000fd5b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119e5576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166355f804b3826040518263ffffffff1660e01b8152600401611a409190614121565b600060405180830381600087803b158015611a5a57600080fd5b505af1158015611a6e573d6000803e3d6000fd5b5050505050565b611a7d613641565b60cd6000838152602001908152602001600020600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820154815250509050919050565b611b49612a51565b611b5282612a9b565b817ff179998d458f1b0e9330ba91242ad9eaf15947e9833e6bf305e031401c782f4182604051611b8291906142fa565b60405180910390a28060cd6000848152602001908152602001600020600201600001819055505050565b60cd6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481525050905085565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d69576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dcf576040517f4c267bfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000611e1d612a51565b611e25612bc1565b611ec96342bfcd2560e01b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168630604051602401611e67939291906146b7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f6b565b905060006040518060a0016040528060016004811115611eec57611eeb613ddb565b5b8152602001866000016020810190611f0491906146f5565b6003811115611f1657611f15613ddb565b5b81526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200185803603810190611f64919061479f565b81525090508060cd600084815260200190815260200160002060008201518160000160006101000a81548160ff02191690836004811115611fa857611fa7613ddb565b5b021790555060208201518160000160016101000a81548160ff02191690836003811115611fd857611fd7613ddb565b5b021790555060408201518160000160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816002016000820151816000015560208201518160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060408201518160010160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816002015550509050508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16837f3f4c8715db6ab1dd28d9a4c95a700e64dacae476b4447291959ed9e6af899f1b60405160405180910390a450612167612d28565b9392505050565b60008060019054906101000a900460ff1615905080801561219f5750600160008054906101000a900460ff1660ff16105b806121cc57506121ae3061303c565b1580156121cb5750600160008054906101000a900460ff1660ff16145b5b61220b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122029061483e565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015612248576001600060016101000a81548160ff0219169083151502179055505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ae576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612314576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361237a576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360ca60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061244561305f565b61244d613159565b6124556131b2565b61245d612f08565b80156124b65760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516124ad91906148a6565b60405180910390a15b50505050565b6124c4612a51565b6124cc612bc1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612532576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61253b82612a9b565b600260cd600084815260200190815260200160002060000160006101000a81548160ff0219169083600481111561257557612574613ddb565b5b02179055506125a960cd600084815260200190815260200160002060000160019054906101000a900460ff1683308461320b565b8073ffffffffffffffffffffffffffffffffffffffff16827f9a7dddb603412cf1089351411dc88dc6a6167550700558b7fa610997c19e7c6f60405160405180910390a36125f5612d28565b5050565b6000603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612685576040517f8daa124600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d060405160405180910390a380603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461280e576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631b86f18c826040518263ffffffff1660e01b815260040161286991906137b0565b600060405180830381600087803b15801561288357600080fd5b505af1158015612897573d6000803e3d6000fd5b5050505050565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b8047101561291a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129119061490d565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516129409061495e565b60006040518083038185875af1925050503d806000811461297d576040519150601f19603f3d011682016040523d82523d6000602084013e612982565b606091505b50509050806129c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129bd906149e5565b60405180910390fd5b505050565b612a4c8363a9059cbb60e01b84846040516024016129ea9291906142c2565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506132ba565b505050565b612a59611123565b15612a99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9090614a51565b60405180910390fd5b565b60cd600082815260200190815260200160002060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015612b5b5750603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15612b92576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612bbe60cd600083815260200190815260200160002060000160009054906101000a900460ff16612e63565b50565b600260665403612c06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bfd90614abd565b60405180910390fd5b6002606681905550565b600360cd600084815260200190815260200160002060000160006101000a81548160ff02191690836004811115612c4a57612c49613ddb565b5b021790555060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3083856040518463ffffffff1660e01b8152600401612cae93929190614add565b600060405180830381600087803b158015612cc857600080fd5b505af1158015612cdc573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16827fdd940b4c0a591c09ff1b1398b5a2a336cb49f986e98a1f8d9fae939fe305be7c60405160405180910390a35050565b6001606681905550565b612d3a613381565b6000609860006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612d7e6133ca565b604051612d8b91906137b0565b60405180910390a1565b600460cd600085815260200190815260200160002060000160006101000a81548160ff02191690836004811115612dcf57612dce613ddb565b5b0217905550612e0360cd600085815260200190815260200160002060000160019054906101000a900460ff1684848461320b565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847fbf98ff69ddbec461405591fb4ae5b1e251f45100f8f9f8b48e2774fa8d585e8f60405160405180910390a4505050565b60016004811115612e7757612e76613ddb565b5b816004811115612e8a57612e89613ddb565b5b14612ecc57806040517ff20f442d000000000000000000000000000000000000000000000000000000008152600401612ec39190614265565b60405180910390fd5b50565b600084848484604051602001612ee89493929190614b41565b604051602081830303815290604052805190602001209050949350505050565b612f10612a51565b6001609860006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612f546133ca565b604051612f6191906137b0565b60405180910390a1565b600080600060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1684604051612fb79190614bb8565b600060405180830381855af49150503d8060008114612ff2576040519150601f19603f3d011682016040523d82523d6000602084013e612ff7565b606091505b50915091508115613030576000815111613012576000613027565b808060200190518101906130269190614158565b5b92505050613037565b8060208201fd5b919050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff166130ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a590614c41565b60405180910390fd5b60006130b86133ca565b905080603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d060405160405180910390a350565b600060019054906101000a900460ff166131a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161319f90614c41565b60405180910390fd5b6131b06133d2565b565b600060019054906101000a900460ff16613201576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131f890614c41565b60405180910390fd5b61320961343e565b565b6132b363dde32c9760e01b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686868686604051602401613251959493929190614c61565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f6b565b5050505050565b600061331c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166134979092919063ffffffff16565b905060008151111561337c578080602001905181019061333c9190614cc9565b61337b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161337290614d68565b60405180910390fd5b5b505050565b613389611123565b6133c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133bf90614dd4565b60405180910390fd5b565b600033905090565b600060019054906101000a900460ff16613421576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161341890614c41565b60405180910390fd5b6000609860006101000a81548160ff021916908315150217905550565b600060019054906101000a900460ff1661348d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161348490614c41565b60405180910390fd5b6001606681905550565b60606134a684846000856134af565b90509392505050565b6060824710156134f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134eb90614e66565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161351d9190614bb8565b60006040518083038185875af1925050503d806000811461355a576040519150601f19603f3d011682016040523d82523d6000602084013e61355f565b606091505b50915091506135708783838761357c565b92505050949350505050565b606083156135de5760008351036135d6576135968561303c565b6135d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135cc90614ed2565b60405180910390fd5b5b8290506135e9565b6135e883836135f1565b5b949350505050565b6000825111156136045781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136389190614121565b60405180910390fd5b604051806080016040528060008019168152602001600067ffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006136cb826136a0565b9050919050565b6136db816136c0565b81146136e657600080fd5b50565b6000813590506136f8816136d2565b92915050565b60006020828403121561371457613713613696565b5b6000613722848285016136e9565b91505092915050565b6000819050919050565b61373e8161372b565b811461374957600080fd5b50565b60008135905061375b81613735565b92915050565b6000806040838503121561377857613777613696565b5b60006137868582860161374c565b9250506020613797858286016136e9565b9150509250929050565b6137aa816136c0565b82525050565b60006020820190506137c560008301846137a1565b92915050565b6000602082840312156137e1576137e0613696565b5b60006137ef8482850161374c565b91505092915050565b600067ffffffffffffffff82169050919050565b613815816137f8565b811461382057600080fd5b50565b6000813590506138328161380c565b92915050565b6000806040838503121561384f5761384e613696565b5b600061385d8582860161374c565b925050602061386e85828601613823565b9150509250929050565b6000819050919050565b600061389d613898613893846136a0565b613878565b6136a0565b9050919050565b60006138af82613882565b9050919050565b60006138c1826138a4565b9050919050565b6138d1816138b6565b82525050565b60006020820190506138ec60008301846138c8565b92915050565b60008115159050919050565b613907816138f2565b82525050565b600060208201905061392260008301846138fe565b92915050565b6000613933826138a4565b9050919050565b61394381613928565b82525050565b600060208201905061395e600083018461393a565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261398957613988613964565b5b8235905067ffffffffffffffff8111156139a6576139a5613969565b5b6020830191508360018202830111156139c2576139c161396e565b5b9250929050565b6139d2816138f2565b81146139dd57600080fd5b50565b6000813590506139ef816139c9565b92915050565b60008060008060008060808789031215613a1257613a11613696565b5b6000613a2089828a0161374c565b965050602087013567ffffffffffffffff811115613a4157613a4061369b565b5b613a4d89828a01613973565b9550955050604087013567ffffffffffffffff811115613a7057613a6f61369b565b5b613a7c89828a01613973565b93509350506060613a8f89828a016139e0565b9150509295509295509295565b600080600060608486031215613ab557613ab4613696565b5b6000613ac38682870161374c565b9350506020613ad4868287016136e9565b9250506040613ae58682870161374c565b9150509250925092565b60008060408385031215613b0657613b05613696565b5b6000613b14858286016136e9565b9250506020613b258582860161374c565b9150509250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b7d82613b34565b810181811067ffffffffffffffff82111715613b9c57613b9b613b45565b5b80604052505050565b6000613baf61368c565b9050613bbb8282613b74565b919050565b600067ffffffffffffffff821115613bdb57613bda613b45565b5b613be482613b34565b9050602081019050919050565b82818337600083830152505050565b6000613c13613c0e84613bc0565b613ba5565b905082815260208101848484011115613c2f57613c2e613b2f565b5b613c3a848285613bf1565b509392505050565b600082601f830112613c5757613c56613964565b5b8135613c67848260208601613c00565b91505092915050565b600060208284031215613c8657613c85613696565b5b600082013567ffffffffffffffff811115613ca457613ca361369b565b5b613cb084828501613c42565b91505092915050565b6000819050919050565b613ccc81613cb9565b82525050565b613cdb816137f8565b82525050565b613cea816136c0565b82525050565b613cf98161372b565b82525050565b608082016000820151613d156000850182613cc3565b506020820151613d286020850182613cd2565b506040820151613d3b6040850182613ce1565b506060820151613d4e6060850182613cf0565b50505050565b6000608082019050613d696000830184613cff565b92915050565b613d7881613cb9565b8114613d8357600080fd5b50565b600081359050613d9581613d6f565b92915050565b60008060408385031215613db257613db1613696565b5b6000613dc08582860161374c565b9250506020613dd185828601613d86565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110613e1b57613e1a613ddb565b5b50565b6000819050613e2c82613e0a565b919050565b6000613e3c82613e1e565b9050919050565b613e4c81613e31565b82525050565b60048110613e6357613e62613ddb565b5b50565b6000819050613e7482613e52565b919050565b6000613e8482613e66565b9050919050565b613e9481613e79565b82525050565b600061010082019050613eb06000830188613e43565b613ebd6020830187613e8b565b613eca60408301866137a1565b613ed760608301856137a1565b613ee46080830184613cff565b9695505050505050565b600080fd5b600060a08284031215613f0957613f08613eee565b5b81905092915050565b600060808284031215613f2857613f27613eee565b5b81905092915050565b600080600060c08486031215613f4a57613f49613696565b5b600084013567ffffffffffffffff811115613f6857613f6761369b565b5b613f7486828701613ef3565b9350506020613f8586828701613f12565b92505060a0613f96868287016136e9565b9150509250925092565b613fa98161372b565b82525050565b6000602082019050613fc46000830184613fa0565b92915050565b6000613fd5826136c0565b9050919050565b613fe581613fca565b8114613ff057600080fd5b50565b60008135905061400281613fdc565b92915050565b6000614013826136c0565b9050919050565b61402381614008565b811461402e57600080fd5b50565b6000813590506140408161401a565b92915050565b60008060006060848603121561405f5761405e613696565b5b600061406d86828701613ff3565b935050602061407e86828701614031565b925050604061408f868287016136e9565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b60005b838110156140d35780820151818401526020810190506140b8565b838111156140e2576000848401525b50505050565b60006140f382614099565b6140fd81856140a4565b935061410d8185602086016140b5565b61411681613b34565b840191505092915050565b6000602082019050818103600083015261413b81846140e8565b905092915050565b60008151905061415281613735565b92915050565b60006020828403121561416e5761416d613696565b5b600061417c84828501614143565b91505092915050565b6000614190826136c0565b9050919050565b6141a081614185565b81146141ab57600080fd5b50565b6000815190506141bd81614197565b92915050565b6000602082840312156141d9576141d8613696565b5b60006141e7848285016141ae565b91505092915050565b600060408201905061420560008301856137a1565b61421260208301846137a1565b9392505050565b600061423461422f61422a846137f8565b613878565b61372b565b9050919050565b61424481614219565b82525050565b600060208201905061425f600083018461423b565b92915050565b600060208201905061427a6000830184613e43565b92915050565b60008151905061428f816136d2565b92915050565b6000602082840312156142ab576142aa613696565b5b60006142b984828501614280565b91505092915050565b60006040820190506142d760008301856137a1565b6142e46020830184613fa0565b9392505050565b6142f481613cb9565b82525050565b600060208201905061430f60008301846142eb565b92915050565b6004811061432257600080fd5b50565b60008135905061433481614315565b92915050565b60006143496020840184614325565b905092915050565b61435a81613e79565b82525050565b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261438c5761438b61436a565b5b83810192508235915060208301925067ffffffffffffffff8211156143b4576143b3614360565b5b6020820236038313156143ca576143c9614365565b5b509250929050565b600082825260208201905092915050565b6000819050919050565b60006143f98383613ce1565b60208301905092915050565b600061441460208401846136e9565b905092915050565b6000602082019050919050565b600061443583856143d2565b9350614440826143e3565b8060005b85811015614479576144568284614405565b61446088826143ed565b975061446b8361441c565b925050600181019050614444565b5085925050509392505050565b600080833560016020038436030381126144a3576144a261436a565b5b83810192508235915060208301925067ffffffffffffffff8211156144cb576144ca614360565b5b6020820236038313156144e1576144e0614365565b5b509250929050565b600082825260208201905092915050565b600080fd5b600061450b83856144e9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561453e5761453d6144fa565b5b60208302925061454f838584613bf1565b82840190509392505050565b600080833560016020038436030381126145785761457761436a565b5b83810192508235915060208301925067ffffffffffffffff8211156145a05761459f614360565b5b6001820236038313156145b6576145b5614365565b5b509250929050565b600082825260208201905092915050565b60006145db83856145be565b93506145e8838584613bf1565b6145f183613b34565b840190509392505050565b600060a0830161460f600084018461433a565b61461c6000860182614351565b5061462a602084018461436f565b858303602087015261463d838284614429565b9250505061464e6040840184614486565b85830360408701526146618382846144ff565b925050506146726060840184614486565b85830360608701526146858382846144ff565b92505050614696608084018461455b565b85830360808701526146a98382846145cf565b925050508091505092915050565b60006060820190506146cc60008301866137a1565b81810360208301526146de81856145fc565b90506146ed60408301846137a1565b949350505050565b60006020828403121561470b5761470a613696565b5b600061471984828501614325565b91505092915050565b600080fd5b60006080828403121561473d5761473c614722565b5b6147476080613ba5565b9050600061475784828501613d86565b600083015250602061476b84828501613823565b602083015250604061477f848285016136e9565b60408301525060606147938482850161374c565b60608301525092915050565b6000608082840312156147b5576147b4613696565b5b60006147c384828501614727565b91505092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614828602e836140a4565b9150614833826147cc565b604082019050919050565b600060208201905081810360008301526148578161481b565b9050919050565b6000819050919050565b600060ff82169050919050565b600061489061488b6148868461485e565b613878565b614868565b9050919050565b6148a081614875565b82525050565b60006020820190506148bb6000830184614897565b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b60006148f7601d836140a4565b9150614902826148c1565b602082019050919050565b60006020820190508181036000830152614926816148ea565b9050919050565b600081905092915050565b50565b600061494860008361492d565b915061495382614938565b600082019050919050565b60006149698261493b565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b60006149cf603a836140a4565b91506149da82614973565b604082019050919050565b600060208201905081810360008301526149fe816149c2565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614a3b6010836140a4565b9150614a4682614a05565b602082019050919050565b60006020820190508181036000830152614a6a81614a2e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614aa7601f836140a4565b9150614ab282614a71565b602082019050919050565b60006020820190508181036000830152614ad681614a9a565b9050919050565b6000606082019050614af260008301866137a1565b614aff60208301856137a1565b614b0c6040830184613fa0565b949350505050565b6000614b2083856140a4565b9350614b2d838584613bf1565b614b3683613b34565b840190509392505050565b60006040820190508181036000830152614b5c818688614b14565b90508181036020830152614b71818486614b14565b905095945050505050565b600081519050919050565b6000614b9282614b7c565b614b9c818561492d565b9350614bac8185602086016140b5565b80840191505092915050565b6000614bc48284614b87565b915081905092915050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614c2b602b836140a4565b9150614c3682614bcf565b604082019050919050565b60006020820190508181036000830152614c5a81614c1e565b9050919050565b600060a082019050614c7660008301886137a1565b614c836020830187613e8b565b614c906040830186613fa0565b614c9d60608301856137a1565b614caa60808301846137a1565b9695505050505050565b600081519050614cc3816139c9565b92915050565b600060208284031215614cdf57614cde613696565b5b6000614ced84828501614cb4565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614d52602a836140a4565b9150614d5d82614cf6565b604082019050919050565b60006020820190508181036000830152614d8181614d45565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000614dbe6014836140a4565b9150614dc982614d88565b602082019050919050565b60006020820190508181036000830152614ded81614db1565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614e506026836140a4565b9150614e5b82614df4565b604082019050919050565b60006020820190508181036000830152614e7f81614e43565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614ebc601d836140a4565b9150614ec782614e86565b602082019050919050565b60006020820190508181036000830152614eeb81614eaf565b905091905056fea26469706673582212200d703cef9ffb11f443275b2a5ea79d54e3b5c860c21ec3cf7a420bcf1413b66564736f6c634300080f0033
Deployed Bytecode
0x6080604052600436106101c25760003560e01c806370cf0f62116100f7578063b61aee8f11610095578063f07a72a511610064578063f07a72a5146105d4578063f3b27bc3146105fd578063fce1264414610614578063ffa1ad741461063d576101c2565b8063b61aee8f14610511578063b6aa515b14610552578063b8ecac0f1461057b578063c0c53b8b146105ab576101c2565b80638d5cdc26116100d15780638d5cdc2614610459578063931688cb146104825780639fd12003146104ab578063a4e04687146104e8576101c2565b806370cf0f62146103ee57806376a90fd6146104195780638456cb5914610442576101c2565b80633f4ba83a116101645780635a9093f71161013e5780635a9093f7146103535780635c975abb1461037c57806366e65b04146103a75780636a5fd500146103d2576101c2565b80633f4ba83a146102e8578063487aac87146102ff5780634c0cc9ad14610328576101c2565b806306d4cc4e116101a057806306d4cc4e146102425780630c340a241461026b57806312150b5d1461029657806334f74482146102bf576101c2565b806301681a62146101c757806303c5a604146101f057806304dad93514610219575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e991906136fe565b610668565b005b3480156101fc57600080fd5b50610217600480360381019061021291906136fe565b610824565b005b34801561022557600080fd5b50610240600480360381019061023b91906136fe565b6109cd565b005b34801561024e57600080fd5b5061026960048036038101906102649190613761565b610ae4565b005b34801561027757600080fd5b50610280610bdf565b60405161028d91906137b0565b60405180910390f35b3480156102a257600080fd5b506102bd60048036038101906102b891906137cb565b610c05565b005b3480156102cb57600080fd5b506102e660048036038101906102e19190613838565b610d5f565b005b3480156102f457600080fd5b506102fd610dec565b005b34801561030b57600080fd5b5061032660048036038101906103219190613761565b610e7d565b005b34801561033457600080fd5b5061033d610f9c565b60405161034a91906138d7565b60405180910390f35b34801561035f57600080fd5b5061037a60048036038101906103759190613761565b610fc2565b005b34801561038857600080fd5b50610391611123565b60405161039e919061390d565b60405180910390f35b3480156103b357600080fd5b506103bc61113a565b6040516103c99190613949565b60405180910390f35b6103ec60048036038101906103e791906139f5565b611160565b005b3480156103fa57600080fd5b506104036116b2565b60405161041091906137b0565b60405180910390f35b34801561042557600080fd5b50610440600480360381019061043b9190613a9c565b6116d8565b005b34801561044e57600080fd5b506104576117b3565b005b34801561046557600080fd5b50610480600480360381019061047b9190613aef565b611844565b005b34801561048e57600080fd5b506104a960048036038101906104a49190613c70565b61195e565b005b3480156104b757600080fd5b506104d260048036038101906104cd91906137cb565b611a75565b6040516104df9190613d54565b60405180910390f35b3480156104f457600080fd5b5061050f600480360381019061050a9190613d9b565b611b41565b005b34801561051d57600080fd5b50610538600480360381019061053391906137cb565b611bac565b604051610549959493929190613e9a565b60405180910390f35b34801561055e57600080fd5b50610579600480360381019061057491906136fe565b611ce2565b005b61059560048036038101906105909190613f31565b611e13565b6040516105a29190613faf565b60405180910390f35b3480156105b757600080fd5b506105d260048036038101906105cd9190614046565b61216e565b005b3480156105e057600080fd5b506105fb60048036038101906105f69190613761565b6124bc565b005b34801561060957600080fd5b506106126125f9565b005b34801561062057600080fd5b5061063b600480360381019061063691906136fe565b612787565b005b34801561064957600080fd5b5061065261289e565b60405161065f9190614121565b60405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106ef576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036107545761074f603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476128d7565b610821565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161078f91906137b0565b602060405180830381865afa1580156107ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d09190614158565b905061081f603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828473ffffffffffffffffffffffffffffffffffffffff166129cb9092919063ffffffff16565b505b50565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146108ab576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093c91906141c3565b73ffffffffffffffffffffffffffffffffffffffff166377394a0b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b81526004016109989291906141f0565b600060405180830381600087803b1580156109b257600080fd5b505af11580156109c6573d6000803e3d6000fd5b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a54576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b826040518263ffffffff1660e01b8152600401610aaf91906137b0565b600060405180830381600087803b158015610ac957600080fd5b505af1158015610add573d6000803e3d6000fd5b5050505050565b610aec612a51565b610af582612a9b565b8073ffffffffffffffffffffffffffffffffffffffff1660cd600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16837f88fe5eceecf1a4a3a6c64c2cf34b14369016f06ae9e9993dc74c3698908c32c260405160405180910390a48060cd600084815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c0d612a51565b610c15612bc1565b600060cd600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610cb6576040517f4834d46700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cbf82612a9b565b4267ffffffffffffffff1660cd600084815260200190815260200160002060020160010160009054906101000a900467ffffffffffffffff1667ffffffffffffffff161115610d49574260cd600084815260200190815260200160002060020160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b610d538282612c10565b50610d5c612d28565b50565b610d67612a51565b610d7082612a9b565b817f20d5405556a3fe0f705a94a30df3ad62f7f464850bb85bb8f1761b437022564782604051610da0919061424a565b60405180910390a28060cd600084815260200190815260200160002060020160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e73576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e7b612d32565b565b610e85612a51565b610e8d612bc1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef3576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060cd600084815260200190815260200160002060000160009054906101000a900460ff16905060036004811115610f2f57610f2e613ddb565b5b816004811115610f4257610f41613ddb565b5b14610f8457806040517ff20f442d000000000000000000000000000000000000000000000000000000008152600401610f7b9190614265565b60405180910390fd5b610f8f833384612d95565b50610f98612d28565b5050565b60ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610fca612a51565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611030576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61103982612a9b565b8073ffffffffffffffffffffffffffffffffffffffff1660cd600084815260200190815260200160002060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16837feb1f466e88badaa63cbff09a15461e10f48e6ccd5c129744bce2c5c8a6da5b3d60405160405180910390a48060cd600084815260200190815260200160002060000160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000609860009054906101000a900460ff16905090565b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611168612a51565b611170612bc1565b61119c60cd600088815260200190815260200160002060000160009054906101000a900460ff16612e63565b600060cd600088815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600060cd6000898152602001908152602001600020600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160028201548152505090506000339050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361132e578092508060cd60008b815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611394565b8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614611393576040517fb40c733e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b42826020015167ffffffffffffffff1611156113dc576040517f83aaa10700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16826040015173ffffffffffffffffffffffffffffffffffffffff16146115e3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260600151036114fb576000826040015173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b815260040161147e91906137b0565b602060405180830381865afa15801561149b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bf9190614158565b036114f6576040517fd988302600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115e2565b3373ffffffffffffffffffffffffffffffffffffffff16826040015173ffffffffffffffffffffffffffffffffffffffff16636352211e84606001516040518263ffffffff1660e01b81526004016115539190613faf565b602060405180830381865afa158015611570573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115949190614295565b73ffffffffffffffffffffffffffffffffffffffff16146115e1576040517fe113e38000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5b6000801b82600001511461163a57816000015161160289898989612ecf565b14611639576040517f1154ef1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8315611694578273ffffffffffffffffffffffffffffffffffffffff16897fdd940b4c0a591c09ff1b1398b5a2a336cb49f986e98a1f8d9fae939fe305be7c60405160405180910390a361168f893085612d95565b61169f565b61169e8984612c10565b5b5050506116aa612d28565b505050505050565b60cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6116e0612a51565b6116e983612a9b565b8173ffffffffffffffffffffffffffffffffffffffff16837fced9903a2507fd2340fce78cf61525e862723bdffda3179cc48f4aa0ec77ab25836040516117309190613faf565b60405180910390a38160cd600085815260200190815260200160002060020160010160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060cd600085815260200190815260200160002060020160020181905550505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461183a576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611842612f08565b565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146118cb576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638d5cdc2683836040518363ffffffff1660e01b81526004016119289291906142c2565b600060405180830381600087803b15801561194257600080fd5b505af1158015611956573d6000803e3d6000fd5b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119e5576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166355f804b3826040518263ffffffff1660e01b8152600401611a409190614121565b600060405180830381600087803b158015611a5a57600080fd5b505af1158015611a6e573d6000803e3d6000fd5b5050505050565b611a7d613641565b60cd6000838152602001908152602001600020600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820154815250509050919050565b611b49612a51565b611b5282612a9b565b817ff179998d458f1b0e9330ba91242ad9eaf15947e9833e6bf305e031401c782f4182604051611b8291906142fa565b60405180910390a28060cd6000848152602001908152602001600020600201600001819055505050565b60cd6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600201604051806080016040529081600082015481526020016001820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481525050905085565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d69576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dcf576040517f4c267bfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000611e1d612a51565b611e25612bc1565b611ec96342bfcd2560e01b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168630604051602401611e67939291906146b7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f6b565b905060006040518060a0016040528060016004811115611eec57611eeb613ddb565b5b8152602001866000016020810190611f0491906146f5565b6003811115611f1657611f15613ddb565b5b81526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200185803603810190611f64919061479f565b81525090508060cd600084815260200190815260200160002060008201518160000160006101000a81548160ff02191690836004811115611fa857611fa7613ddb565b5b021790555060208201518160000160016101000a81548160ff02191690836003811115611fd857611fd7613ddb565b5b021790555060408201518160000160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816002016000820151816000015560208201518160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060408201518160010160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816002015550509050508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16837f3f4c8715db6ab1dd28d9a4c95a700e64dacae476b4447291959ed9e6af899f1b60405160405180910390a450612167612d28565b9392505050565b60008060019054906101000a900460ff1615905080801561219f5750600160008054906101000a900460ff1660ff16105b806121cc57506121ae3061303c565b1580156121cb5750600160008054906101000a900460ff1660ff16145b5b61220b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122029061483e565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015612248576001600060016101000a81548160ff0219169083151502179055505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ae576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612314576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361237a576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360ca60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260cb60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160cc60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061244561305f565b61244d613159565b6124556131b2565b61245d612f08565b80156124b65760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516124ad91906148a6565b60405180910390a15b50505050565b6124c4612a51565b6124cc612bc1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612532576040517ffb7566d700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61253b82612a9b565b600260cd600084815260200190815260200160002060000160006101000a81548160ff0219169083600481111561257557612574613ddb565b5b02179055506125a960cd600084815260200190815260200160002060000160019054906101000a900460ff1683308461320b565b8073ffffffffffffffffffffffffffffffffffffffff16827f9a7dddb603412cf1089351411dc88dc6a6167550700558b7fa610997c19e7c6f60405160405180910390a36125f5612d28565b5050565b6000603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612685576040517f8daa124600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d060405160405180910390a380603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b3373ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461280e576040517f07f42bf200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631b86f18c826040518263ffffffff1660e01b815260040161286991906137b0565b600060405180830381600087803b15801561288357600080fd5b505af1158015612897573d6000803e3d6000fd5b5050505050565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b8047101561291a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129119061490d565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516129409061495e565b60006040518083038185875af1925050503d806000811461297d576040519150601f19603f3d011682016040523d82523d6000602084013e612982565b606091505b50509050806129c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129bd906149e5565b60405180910390fd5b505050565b612a4c8363a9059cbb60e01b84846040516024016129ea9291906142c2565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506132ba565b505050565b612a59611123565b15612a99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9090614a51565b60405180910390fd5b565b60cd600082815260200190815260200160002060000160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015612b5b5750603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15612b92576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612bbe60cd600083815260200190815260200160002060000160009054906101000a900460ff16612e63565b50565b600260665403612c06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bfd90614abd565b60405180910390fd5b6002606681905550565b600360cd600084815260200190815260200160002060000160006101000a81548160ff02191690836004811115612c4a57612c49613ddb565b5b021790555060cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3083856040518463ffffffff1660e01b8152600401612cae93929190614add565b600060405180830381600087803b158015612cc857600080fd5b505af1158015612cdc573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff16827fdd940b4c0a591c09ff1b1398b5a2a336cb49f986e98a1f8d9fae939fe305be7c60405160405180910390a35050565b6001606681905550565b612d3a613381565b6000609860006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612d7e6133ca565b604051612d8b91906137b0565b60405180910390a1565b600460cd600085815260200190815260200160002060000160006101000a81548160ff02191690836004811115612dcf57612dce613ddb565b5b0217905550612e0360cd600085815260200190815260200160002060000160019054906101000a900460ff1684848461320b565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847fbf98ff69ddbec461405591fb4ae5b1e251f45100f8f9f8b48e2774fa8d585e8f60405160405180910390a4505050565b60016004811115612e7757612e76613ddb565b5b816004811115612e8a57612e89613ddb565b5b14612ecc57806040517ff20f442d000000000000000000000000000000000000000000000000000000008152600401612ec39190614265565b60405180910390fd5b50565b600084848484604051602001612ee89493929190614b41565b604051602081830303815290604052805190602001209050949350505050565b612f10612a51565b6001609860006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612f546133ca565b604051612f6191906137b0565b60405180910390a1565b600080600060cc60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1684604051612fb79190614bb8565b600060405180830381855af49150503d8060008114612ff2576040519150601f19603f3d011682016040523d82523d6000602084013e612ff7565b606091505b50915091508115613030576000815111613012576000613027565b808060200190518101906130269190614158565b5b92505050613037565b8060208201fd5b919050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600060019054906101000a900460ff166130ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a590614c41565b60405180910390fd5b60006130b86133ca565b905080603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d060405160405180910390a350565b600060019054906101000a900460ff166131a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161319f90614c41565b60405180910390fd5b6131b06133d2565b565b600060019054906101000a900460ff16613201576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131f890614c41565b60405180910390fd5b61320961343e565b565b6132b363dde32c9760e01b60cb60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686868686604051602401613251959493929190614c61565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f6b565b5050505050565b600061331c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166134979092919063ffffffff16565b905060008151111561337c578080602001905181019061333c9190614cc9565b61337b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161337290614d68565b60405180910390fd5b5b505050565b613389611123565b6133c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133bf90614dd4565b60405180910390fd5b565b600033905090565b600060019054906101000a900460ff16613421576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161341890614c41565b60405180910390fd5b6000609860006101000a81548160ff021916908315150217905550565b600060019054906101000a900460ff1661348d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161348490614c41565b60405180910390fd5b6001606681905550565b60606134a684846000856134af565b90509392505050565b6060824710156134f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134eb90614e66565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161351d9190614bb8565b60006040518083038185875af1925050503d806000811461355a576040519150601f19603f3d011682016040523d82523d6000602084013e61355f565b606091505b50915091506135708783838761357c565b92505050949350505050565b606083156135de5760008351036135d6576135968561303c565b6135d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135cc90614ed2565b60405180910390fd5b5b8290506135e9565b6135e883836135f1565b5b949350505050565b6000825111156136045781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136389190614121565b60405180910390fd5b604051806080016040528060008019168152602001600067ffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006136cb826136a0565b9050919050565b6136db816136c0565b81146136e657600080fd5b50565b6000813590506136f8816136d2565b92915050565b60006020828403121561371457613713613696565b5b6000613722848285016136e9565b91505092915050565b6000819050919050565b61373e8161372b565b811461374957600080fd5b50565b60008135905061375b81613735565b92915050565b6000806040838503121561377857613777613696565b5b60006137868582860161374c565b9250506020613797858286016136e9565b9150509250929050565b6137aa816136c0565b82525050565b60006020820190506137c560008301846137a1565b92915050565b6000602082840312156137e1576137e0613696565b5b60006137ef8482850161374c565b91505092915050565b600067ffffffffffffffff82169050919050565b613815816137f8565b811461382057600080fd5b50565b6000813590506138328161380c565b92915050565b6000806040838503121561384f5761384e613696565b5b600061385d8582860161374c565b925050602061386e85828601613823565b9150509250929050565b6000819050919050565b600061389d613898613893846136a0565b613878565b6136a0565b9050919050565b60006138af82613882565b9050919050565b60006138c1826138a4565b9050919050565b6138d1816138b6565b82525050565b60006020820190506138ec60008301846138c8565b92915050565b60008115159050919050565b613907816138f2565b82525050565b600060208201905061392260008301846138fe565b92915050565b6000613933826138a4565b9050919050565b61394381613928565b82525050565b600060208201905061395e600083018461393a565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261398957613988613964565b5b8235905067ffffffffffffffff8111156139a6576139a5613969565b5b6020830191508360018202830111156139c2576139c161396e565b5b9250929050565b6139d2816138f2565b81146139dd57600080fd5b50565b6000813590506139ef816139c9565b92915050565b60008060008060008060808789031215613a1257613a11613696565b5b6000613a2089828a0161374c565b965050602087013567ffffffffffffffff811115613a4157613a4061369b565b5b613a4d89828a01613973565b9550955050604087013567ffffffffffffffff811115613a7057613a6f61369b565b5b613a7c89828a01613973565b93509350506060613a8f89828a016139e0565b9150509295509295509295565b600080600060608486031215613ab557613ab4613696565b5b6000613ac38682870161374c565b9350506020613ad4868287016136e9565b9250506040613ae58682870161374c565b9150509250925092565b60008060408385031215613b0657613b05613696565b5b6000613b14858286016136e9565b9250506020613b258582860161374c565b9150509250929050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b7d82613b34565b810181811067ffffffffffffffff82111715613b9c57613b9b613b45565b5b80604052505050565b6000613baf61368c565b9050613bbb8282613b74565b919050565b600067ffffffffffffffff821115613bdb57613bda613b45565b5b613be482613b34565b9050602081019050919050565b82818337600083830152505050565b6000613c13613c0e84613bc0565b613ba5565b905082815260208101848484011115613c2f57613c2e613b2f565b5b613c3a848285613bf1565b509392505050565b600082601f830112613c5757613c56613964565b5b8135613c67848260208601613c00565b91505092915050565b600060208284031215613c8657613c85613696565b5b600082013567ffffffffffffffff811115613ca457613ca361369b565b5b613cb084828501613c42565b91505092915050565b6000819050919050565b613ccc81613cb9565b82525050565b613cdb816137f8565b82525050565b613cea816136c0565b82525050565b613cf98161372b565b82525050565b608082016000820151613d156000850182613cc3565b506020820151613d286020850182613cd2565b506040820151613d3b6040850182613ce1565b506060820151613d4e6060850182613cf0565b50505050565b6000608082019050613d696000830184613cff565b92915050565b613d7881613cb9565b8114613d8357600080fd5b50565b600081359050613d9581613d6f565b92915050565b60008060408385031215613db257613db1613696565b5b6000613dc08582860161374c565b9250506020613dd185828601613d86565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110613e1b57613e1a613ddb565b5b50565b6000819050613e2c82613e0a565b919050565b6000613e3c82613e1e565b9050919050565b613e4c81613e31565b82525050565b60048110613e6357613e62613ddb565b5b50565b6000819050613e7482613e52565b919050565b6000613e8482613e66565b9050919050565b613e9481613e79565b82525050565b600061010082019050613eb06000830188613e43565b613ebd6020830187613e8b565b613eca60408301866137a1565b613ed760608301856137a1565b613ee46080830184613cff565b9695505050505050565b600080fd5b600060a08284031215613f0957613f08613eee565b5b81905092915050565b600060808284031215613f2857613f27613eee565b5b81905092915050565b600080600060c08486031215613f4a57613f49613696565b5b600084013567ffffffffffffffff811115613f6857613f6761369b565b5b613f7486828701613ef3565b9350506020613f8586828701613f12565b92505060a0613f96868287016136e9565b9150509250925092565b613fa98161372b565b82525050565b6000602082019050613fc46000830184613fa0565b92915050565b6000613fd5826136c0565b9050919050565b613fe581613fca565b8114613ff057600080fd5b50565b60008135905061400281613fdc565b92915050565b6000614013826136c0565b9050919050565b61402381614008565b811461402e57600080fd5b50565b6000813590506140408161401a565b92915050565b60008060006060848603121561405f5761405e613696565b5b600061406d86828701613ff3565b935050602061407e86828701614031565b925050604061408f868287016136e9565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b60005b838110156140d35780820151818401526020810190506140b8565b838111156140e2576000848401525b50505050565b60006140f382614099565b6140fd81856140a4565b935061410d8185602086016140b5565b61411681613b34565b840191505092915050565b6000602082019050818103600083015261413b81846140e8565b905092915050565b60008151905061415281613735565b92915050565b60006020828403121561416e5761416d613696565b5b600061417c84828501614143565b91505092915050565b6000614190826136c0565b9050919050565b6141a081614185565b81146141ab57600080fd5b50565b6000815190506141bd81614197565b92915050565b6000602082840312156141d9576141d8613696565b5b60006141e7848285016141ae565b91505092915050565b600060408201905061420560008301856137a1565b61421260208301846137a1565b9392505050565b600061423461422f61422a846137f8565b613878565b61372b565b9050919050565b61424481614219565b82525050565b600060208201905061425f600083018461423b565b92915050565b600060208201905061427a6000830184613e43565b92915050565b60008151905061428f816136d2565b92915050565b6000602082840312156142ab576142aa613696565b5b60006142b984828501614280565b91505092915050565b60006040820190506142d760008301856137a1565b6142e46020830184613fa0565b9392505050565b6142f481613cb9565b82525050565b600060208201905061430f60008301846142eb565b92915050565b6004811061432257600080fd5b50565b60008135905061433481614315565b92915050565b60006143496020840184614325565b905092915050565b61435a81613e79565b82525050565b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261438c5761438b61436a565b5b83810192508235915060208301925067ffffffffffffffff8211156143b4576143b3614360565b5b6020820236038313156143ca576143c9614365565b5b509250929050565b600082825260208201905092915050565b6000819050919050565b60006143f98383613ce1565b60208301905092915050565b600061441460208401846136e9565b905092915050565b6000602082019050919050565b600061443583856143d2565b9350614440826143e3565b8060005b85811015614479576144568284614405565b61446088826143ed565b975061446b8361441c565b925050600181019050614444565b5085925050509392505050565b600080833560016020038436030381126144a3576144a261436a565b5b83810192508235915060208301925067ffffffffffffffff8211156144cb576144ca614360565b5b6020820236038313156144e1576144e0614365565b5b509250929050565b600082825260208201905092915050565b600080fd5b600061450b83856144e9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561453e5761453d6144fa565b5b60208302925061454f838584613bf1565b82840190509392505050565b600080833560016020038436030381126145785761457761436a565b5b83810192508235915060208301925067ffffffffffffffff8211156145a05761459f614360565b5b6001820236038313156145b6576145b5614365565b5b509250929050565b600082825260208201905092915050565b60006145db83856145be565b93506145e8838584613bf1565b6145f183613b34565b840190509392505050565b600060a0830161460f600084018461433a565b61461c6000860182614351565b5061462a602084018461436f565b858303602087015261463d838284614429565b9250505061464e6040840184614486565b85830360408701526146618382846144ff565b925050506146726060840184614486565b85830360608701526146858382846144ff565b92505050614696608084018461455b565b85830360808701526146a98382846145cf565b925050508091505092915050565b60006060820190506146cc60008301866137a1565b81810360208301526146de81856145fc565b90506146ed60408301846137a1565b949350505050565b60006020828403121561470b5761470a613696565b5b600061471984828501614325565b91505092915050565b600080fd5b60006080828403121561473d5761473c614722565b5b6147476080613ba5565b9050600061475784828501613d86565b600083015250602061476b84828501613823565b602083015250604061477f848285016136e9565b60408301525060606147938482850161374c565b60608301525092915050565b6000608082840312156147b5576147b4613696565b5b60006147c384828501614727565b91505092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614828602e836140a4565b9150614833826147cc565b604082019050919050565b600060208201905081810360008301526148578161481b565b9050919050565b6000819050919050565b600060ff82169050919050565b600061489061488b6148868461485e565b613878565b614868565b9050919050565b6148a081614875565b82525050565b60006020820190506148bb6000830184614897565b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b60006148f7601d836140a4565b9150614902826148c1565b602082019050919050565b60006020820190508181036000830152614926816148ea565b9050919050565b600081905092915050565b50565b600061494860008361492d565b915061495382614938565b600082019050919050565b60006149698261493b565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b60006149cf603a836140a4565b91506149da82614973565b604082019050919050565b600060208201905081810360008301526149fe816149c2565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000614a3b6010836140a4565b9150614a4682614a05565b602082019050919050565b60006020820190508181036000830152614a6a81614a2e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614aa7601f836140a4565b9150614ab282614a71565b602082019050919050565b60006020820190508181036000830152614ad681614a9a565b9050919050565b6000606082019050614af260008301866137a1565b614aff60208301856137a1565b614b0c6040830184613fa0565b949350505050565b6000614b2083856140a4565b9350614b2d838584613bf1565b614b3683613b34565b840190509392505050565b60006040820190508181036000830152614b5c818688614b14565b90508181036020830152614b71818486614b14565b905095945050505050565b600081519050919050565b6000614b9282614b7c565b614b9c818561492d565b9350614bac8185602086016140b5565b80840191505092915050565b6000614bc48284614b87565b915081905092915050565b7f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960008201527f6e697469616c697a696e67000000000000000000000000000000000000000000602082015250565b6000614c2b602b836140a4565b9150614c3682614bcf565b604082019050919050565b60006020820190508181036000830152614c5a81614c1e565b9050919050565b600060a082019050614c7660008301886137a1565b614c836020830187613e8b565b614c906040830186613fa0565b614c9d60608301856137a1565b614caa60808301846137a1565b9695505050505050565b600081519050614cc3816139c9565b92915050565b600060208284031215614cdf57614cde613696565b5b6000614ced84828501614cb4565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614d52602a836140a4565b9150614d5d82614cf6565b604082019050919050565b60006020820190508181036000830152614d8181614d45565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b6000614dbe6014836140a4565b9150614dc982614d88565b602082019050919050565b60006020820190508181036000830152614ded81614db1565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614e506026836140a4565b9150614e5b82614df4565b604082019050919050565b60006020820190508181036000830152614e7f81614e43565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614ebc601d836140a4565b9150614ec782614e86565b602082019050919050565b60006020820190508181036000830152614eeb81614eaf565b905091905056fea26469706673582212200d703cef9ffb11f443275b2a5ea79d54e3b5c860c21ec3cf7a420bcf1413b66564736f6c634300080f0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.