Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 58 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer From | 17914926 | 927 days ago | IN | 0 ETH | 0.0015905 | ||||
| Mint | 17220150 | 1024 days ago | IN | 0.025 ETH | 0.00740415 | ||||
| Mint | 17145901 | 1035 days ago | IN | 0.025 ETH | 0.00272354 | ||||
| Mint | 17118737 | 1038 days ago | IN | 0 ETH | 0.00171173 | ||||
| Mint | 17104080 | 1041 days ago | IN | 0.05 ETH | 0.00387934 | ||||
| Mint | 17102022 | 1041 days ago | IN | 0.125 ETH | 0.0066622 | ||||
| Mint | 17091708 | 1042 days ago | IN | 0.1 ETH | 0.00680907 | ||||
| Mint | 17089033 | 1043 days ago | IN | 0.025 ETH | 0.0067942 | ||||
| Mint | 17089026 | 1043 days ago | IN | 0.125 ETH | 0.01650048 | ||||
| Mint | 17089019 | 1043 days ago | IN | 0.125 ETH | 0.02014637 | ||||
| Release | 17088207 | 1043 days ago | IN | 0 ETH | 0.0048254 | ||||
| Release | 17088084 | 1043 days ago | IN | 0 ETH | 0.00528985 | ||||
| Mint | 17081721 | 1044 days ago | IN | 0.025 ETH | 0.00747731 | ||||
| Mint | 17075296 | 1045 days ago | IN | 0.025 ETH | 0.00742655 | ||||
| Mint | 17068546 | 1046 days ago | IN | 0.025 ETH | 0.00415115 | ||||
| Mint | 17065642 | 1046 days ago | IN | 0.025 ETH | 0.00181721 | ||||
| Mint | 17053728 | 1048 days ago | IN | 0.2 ETH | 0.00760504 | ||||
| Mint | 17053717 | 1048 days ago | IN | 0.025 ETH | 0.00247138 | ||||
| Mint | 17053405 | 1048 days ago | IN | 0.025 ETH | 0.00214518 | ||||
| Mint | 17053191 | 1048 days ago | IN | 0.025 ETH | 0.00308239 | ||||
| Mint | 17053174 | 1048 days ago | IN | 0.025 ETH | 0.00282614 | ||||
| Mint | 17049286 | 1048 days ago | IN | 0.025 ETH | 0.00184293 | ||||
| Mint | 17048817 | 1048 days ago | IN | 0.25 ETH | 0.0086023 | ||||
| Mint | 17048802 | 1048 days ago | IN | 0.25 ETH | 0.007998 | ||||
| Mint | 17048782 | 1048 days ago | IN | 0.05 ETH | 0.00248565 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MFC01
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "@openzeppelin/contracts/finance/PaymentSplitter.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MFC01 is ERC2981, ERC721, PaymentSplitter, Ownable {
using SafeMath for uint256;
using Counters for Counters.Counter;
bool saleIsActive = true;
string defaultBaseURI;
uint256 maxSupply;
uint256 maxQuantity;
uint256 salePrice;
Counters.Counter private tokenIds;
string public imageHash = "2705e2f93aba299ed890204f03fd01d56f16a5ba2cec0492d4b02d506b35dbcc";
constructor(
address[] memory payees,
uint256[] memory shares,
address royaltiesReceiver,
uint96 royaltiesFeeNumerator
) payable ERC721("Michael Taaffe Collection", "MFCMT") PaymentSplitter(payees, shares) {
defaultBaseURI = "https://metadata.monsterfanclub.net/mfc01/";
salePrice = 25000000000000000;
maxSupply = 250;
maxQuantity = 10;
_setDefaultRoyalty(royaltiesReceiver, royaltiesFeeNumerator);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _baseURI() internal view override returns (string memory) {
return defaultBaseURI;
}
function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyOwner {
_setDefaultRoyalty(receiver, feeNumerator);
}
function setBaseURI(string memory newBaseURI_) external onlyOwner {
defaultBaseURI = newBaseURI_;
}
function setSalePrice(uint256 salePrice_) external onlyOwner {
salePrice = salePrice_;
}
function currentTokenId() public view returns (uint256){
return tokenIds.current();
}
function toggleSaleState() public onlyOwner {
saleIsActive = !saleIsActive;
}
function _mintTicket(address recipient_) private returns (uint256) {
tokenIds.increment();
_safeMint(recipient_, tokenIds.current());
return tokenIds.current();
}
function mint(uint256 quantity) public payable {
require(saleIsActive, "Sale is not active");
require(msg.value >= salePrice.mul(quantity), "Not enough ETH to mint NFTS");
require(quantity <= maxQuantity, "Exceeded max quantity");
require(tokenIds.current() + quantity <= maxSupply, "Exceeded max limit of allowed token mints");
for (uint256 i = 0; i < quantity; i++) {
_mintTicket(msg.sender);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (finance/PaymentSplitter.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
/**
* @title PaymentSplitter
* @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
* that the Ether will be split in this way, since it is handled transparently by the contract.
*
* The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
* account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
* an amount proportional to the percentage of total shares they were assigned. The distribution of shares is set at the
* time of contract deployment and can't be updated thereafter.
*
* `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
* accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
* function.
*
* NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
* tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
* to run tests before sending real value to this contract.
*/
contract PaymentSplitter is Context {
event PayeeAdded(address account, uint256 shares);
event PaymentReleased(address to, uint256 amount);
event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
event PaymentReceived(address from, uint256 amount);
uint256 private _totalShares;
uint256 private _totalReleased;
mapping(address => uint256) private _shares;
mapping(address => uint256) private _released;
address[] private _payees;
mapping(IERC20 => uint256) private _erc20TotalReleased;
mapping(IERC20 => mapping(address => uint256)) private _erc20Released;
/**
* @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
* the matching position in the `shares` array.
*
* All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
* duplicates in `payees`.
*/
constructor(address[] memory payees, uint256[] memory shares_) payable {
require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
require(payees.length > 0, "PaymentSplitter: no payees");
for (uint256 i = 0; i < payees.length; i++) {
_addPayee(payees[i], shares_[i]);
}
}
/**
* @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
* reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
* reliability of the events, and not the actual splitting of Ether.
*
* To learn more about this see the Solidity documentation for
* https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
* functions].
*/
receive() external payable virtual {
emit PaymentReceived(_msgSender(), msg.value);
}
/**
* @dev Getter for the total shares held by payees.
*/
function totalShares() public view returns (uint256) {
return _totalShares;
}
/**
* @dev Getter for the total amount of Ether already released.
*/
function totalReleased() public view returns (uint256) {
return _totalReleased;
}
/**
* @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
* contract.
*/
function totalReleased(IERC20 token) public view returns (uint256) {
return _erc20TotalReleased[token];
}
/**
* @dev Getter for the amount of shares held by an account.
*/
function shares(address account) public view returns (uint256) {
return _shares[account];
}
/**
* @dev Getter for the amount of Ether already released to a payee.
*/
function released(address account) public view returns (uint256) {
return _released[account];
}
/**
* @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
* IERC20 contract.
*/
function released(IERC20 token, address account) public view returns (uint256) {
return _erc20Released[token][account];
}
/**
* @dev Getter for the address of the payee number `index`.
*/
function payee(uint256 index) public view returns (address) {
return _payees[index];
}
/**
* @dev Getter for the amount of payee's releasable Ether.
*/
function releasable(address account) public view returns (uint256) {
uint256 totalReceived = address(this).balance + totalReleased();
return _pendingPayment(account, totalReceived, released(account));
}
/**
* @dev Getter for the amount of payee's releasable `token` tokens. `token` should be the address of an
* IERC20 contract.
*/
function releasable(IERC20 token, address account) public view returns (uint256) {
uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
return _pendingPayment(account, totalReceived, released(token, account));
}
/**
* @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
* total shares and their previous withdrawals.
*/
function release(address payable account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 payment = releasable(account);
require(payment != 0, "PaymentSplitter: account is not due payment");
// _totalReleased is the sum of all values in _released.
// If "_totalReleased += payment" does not overflow, then "_released[account] += payment" cannot overflow.
_totalReleased += payment;
unchecked {
_released[account] += payment;
}
Address.sendValue(account, payment);
emit PaymentReleased(account, payment);
}
/**
* @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
* percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
* contract.
*/
function release(IERC20 token, address account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 payment = releasable(token, account);
require(payment != 0, "PaymentSplitter: account is not due payment");
// _erc20TotalReleased[token] is the sum of all values in _erc20Released[token].
// If "_erc20TotalReleased[token] += payment" does not overflow, then "_erc20Released[token][account] += payment"
// cannot overflow.
_erc20TotalReleased[token] += payment;
unchecked {
_erc20Released[token][account] += payment;
}
SafeERC20.safeTransfer(token, account, payment);
emit ERC20PaymentReleased(token, account, payment);
}
/**
* @dev internal logic for computing the pending payment of an `account` given the token historical balances and
* already released amounts.
*/
function _pendingPayment(
address account,
uint256 totalReceived,
uint256 alreadyReleased
) private view returns (uint256) {
return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
}
/**
* @dev Add a new payee to the contract.
* @param account The address of the payee to add.
* @param shares_ The number of shares owned by the payee.
*/
function _addPayee(address account, uint256 shares_) private {
require(account != address(0), "PaymentSplitter: account is the zero address");
require(shares_ > 0, "PaymentSplitter: shares are 0");
require(_shares[account] == 0, "PaymentSplitter: account already has shares");
_payees.push(account);
_shares[account] = shares_;
_totalShares = _totalShares + shares_;
emit PayeeAdded(account, shares_);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.0;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(
uint256 tokenId,
address receiver,
uint96 feeNumerator
) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @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.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/
// solhint-disable-next-line func-name-mixedcase
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (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 v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// 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 (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"},{"internalType":"address","name":"royaltiesReceiver","type":"address"},{"internalType":"uint96","name":"royaltiesFeeNumerator","type":"uint96"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"PayeeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"imageHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"payee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"releasable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"releasable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"salePrice_","type":"uint256"}],"name":"setSalePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60806040526001600f60146101000a81548160ff0219169083151502179055506040518060600160405280604081526020016200622c6040913960159081620000499190620009b5565b50604051620062963803806200629683398181016040528101906200006f919062000dab565b83836040518060400160405280601981526020017f4d69636861656c2054616166666520436f6c6c656374696f6e000000000000008152506040518060400160405280600581526020017f4d46434d540000000000000000000000000000000000000000000000000000008152508160029081620000ee9190620009b5565b508060039081620001009190620009b5565b50505080518251146200014a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001419062000ee2565b60405180910390fd5b600082511162000191576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001889062000f54565b60405180910390fd5b60005b82518110156200020057620001ea838281518110620001b857620001b762000f76565b5b6020026020010151838381518110620001d657620001d562000f76565b5b60200260200101516200028860201b60201c565b8080620001f79062000fd4565b91505062000194565b5050506200022362000217620004c160201b60201c565b620004c960201b60201c565b6040518060600160405280602a81526020016200626c602a9139601090816200024d9190620009b5565b506658d15e1762800060138190555060fa601181905550600a6012819055506200027e82826200058f60201b60201c565b5050505062001357565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620002fa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002f19062001097565b60405180910390fd5b6000811162000340576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003379062001109565b60405180910390fd5b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414620003c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003bc90620011a1565b60405180910390fd5b600c829080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806008546200047c9190620011c3565b6008819055507f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac8282604051620004b592919062001220565b60405180910390a15050565b600033905090565b6000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6200059f6200073160201b60201c565b6bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562000600576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005f790620012c3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000672576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006699062001335565b60405180910390fd5b60405180604001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001826bffffffffffffffffffffffff168152506000808201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055509050505050565b6000612710905090565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620007bd57607f821691505b602082108103620007d357620007d262000775565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200083d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620007fe565b620008498683620007fe565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000896620008906200088a8462000861565b6200086b565b62000861565b9050919050565b6000819050919050565b620008b28362000875565b620008ca620008c1826200089d565b8484546200080b565b825550505050565b600090565b620008e1620008d2565b620008ee818484620008a7565b505050565b5b8181101562000916576200090a600082620008d7565b600181019050620008f4565b5050565b601f82111562000965576200092f81620007d9565b6200093a84620007ee565b810160208510156200094a578190505b620009626200095985620007ee565b830182620008f3565b50505b505050565b600082821c905092915050565b60006200098a600019846008026200096a565b1980831691505092915050565b6000620009a5838362000977565b9150826002028217905092915050565b620009c0826200073b565b67ffffffffffffffff811115620009dc57620009db62000746565b5b620009e88254620007a4565b620009f58282856200091a565b600060209050601f83116001811462000a2d576000841562000a18578287015190505b62000a24858262000997565b86555062000a94565b601f19841662000a3d86620007d9565b60005b8281101562000a675784890151825560018201915060208501945060208101905062000a40565b8683101562000a87578489015162000a83601f89168262000977565b8355505b6001600288020188555050505b505050505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b62000ad18262000ab5565b810181811067ffffffffffffffff8211171562000af35762000af262000746565b5b80604052505050565b600062000b0862000a9c565b905062000b16828262000ac6565b919050565b600067ffffffffffffffff82111562000b395762000b3862000746565b5b602082029050602081019050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000b7c8262000b4f565b9050919050565b62000b8e8162000b6f565b811462000b9a57600080fd5b50565b60008151905062000bae8162000b83565b92915050565b600062000bcb62000bc58462000b1b565b62000afc565b9050808382526020820190506020840283018581111562000bf15762000bf062000b4a565b5b835b8181101562000c1e578062000c09888262000b9d565b84526020840193505060208101905062000bf3565b5050509392505050565b600082601f83011262000c405762000c3f62000ab0565b5b815162000c5284826020860162000bb4565b91505092915050565b600067ffffffffffffffff82111562000c795762000c7862000746565b5b602082029050602081019050919050565b62000c958162000861565b811462000ca157600080fd5b50565b60008151905062000cb58162000c8a565b92915050565b600062000cd262000ccc8462000c5b565b62000afc565b9050808382526020820190506020840283018581111562000cf85762000cf762000b4a565b5b835b8181101562000d25578062000d10888262000ca4565b84526020840193505060208101905062000cfa565b5050509392505050565b600082601f83011262000d475762000d4662000ab0565b5b815162000d5984826020860162000cbb565b91505092915050565b60006bffffffffffffffffffffffff82169050919050565b62000d858162000d62565b811462000d9157600080fd5b50565b60008151905062000da58162000d7a565b92915050565b6000806000806080858703121562000dc85762000dc762000aa6565b5b600085015167ffffffffffffffff81111562000de95762000de862000aab565b5b62000df78782880162000c28565b945050602085015167ffffffffffffffff81111562000e1b5762000e1a62000aab565b5b62000e298782880162000d2f565b935050604062000e3c8782880162000b9d565b925050606062000e4f8782880162000d94565b91505092959194509250565b600082825260208201905092915050565b7f5061796d656e7453706c69747465723a2070617965657320616e64207368617260008201527f6573206c656e677468206d69736d617463680000000000000000000000000000602082015250565b600062000eca60328362000e5b565b915062000ed78262000e6c565b604082019050919050565b6000602082019050818103600083015262000efd8162000ebb565b9050919050565b7f5061796d656e7453706c69747465723a206e6f20706179656573000000000000600082015250565b600062000f3c601a8362000e5b565b915062000f498262000f04565b602082019050919050565b6000602082019050818103600083015262000f6f8162000f2d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000fe18262000861565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362001016576200101562000fa5565b5b600182019050919050565b7f5061796d656e7453706c69747465723a206163636f756e74206973207468652060008201527f7a65726f20616464726573730000000000000000000000000000000000000000602082015250565b60006200107f602c8362000e5b565b91506200108c8262001021565b604082019050919050565b60006020820190508181036000830152620010b28162001070565b9050919050565b7f5061796d656e7453706c69747465723a20736861726573206172652030000000600082015250565b6000620010f1601d8362000e5b565b9150620010fe82620010b9565b602082019050919050565b600060208201905081810360008301526200112481620010e2565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e7420616c726561647960008201527f2068617320736861726573000000000000000000000000000000000000000000602082015250565b600062001189602b8362000e5b565b915062001196826200112b565b604082019050919050565b60006020820190508181036000830152620011bc816200117a565b9050919050565b6000620011d08262000861565b9150620011dd8362000861565b9250828201905080821115620011f857620011f762000fa5565b5b92915050565b620012098162000b6f565b82525050565b6200121a8162000861565b82525050565b6000604082019050620012376000830185620011fe565b6200124660208301846200120f565b9392505050565b7f455243323938313a20726f79616c7479206665652077696c6c2065786365656460008201527f2073616c65507269636500000000000000000000000000000000000000000000602082015250565b6000620012ab602a8362000e5b565b9150620012b8826200124d565b604082019050919050565b60006020820190508181036000830152620012de816200129c565b9050919050565b7f455243323938313a20696e76616c696420726563656976657200000000000000600082015250565b60006200131d60198362000e5b565b91506200132a82620012e5565b602082019050919050565b6000602082019050818103600083015262001350816200130e565b9050919050565b614ec580620013676000396000f3fe6080604052600436106102075760003560e01c806370a0823111610118578063b88d4fde116100a0578063d79779b21161006f578063d79779b2146107ff578063daaeec861461083c578063e33b7de314610853578063e985e9c51461087e578063f2fde38b146108bb5761024e565b8063b88d4fde1461071f578063c45ac05014610748578063c87b56dd14610785578063ce7c2ac2146107c25761024e565b806395d89b41116100e757806395d89b41146106355780639852595c14610660578063a0712d681461069d578063a22cb465146106b9578063a3f8eace146106e25761024e565b806370a0823114610579578063715018a6146105b65780638b83209b146105cd5780638da5cb5b1461060a5761024e565b806323b872dd1161019b57806342842e0e1161016a57806342842e0e1461049657806348b75044146104bf57806351605d80146104e857806355f804b3146105135780636352211e1461053c5761024e565b806323b872dd146103c75780632a55205a146103f05780633a98ef391461042e578063406072a9146104595761024e565b8063081812fc116101d7578063081812fc1461030f578063095ea7b31461034c57806319165587146103755780631919fed71461039e5761024e565b80629a9b7b1461025357806301ffc9a71461027e57806304634d8d146102bb57806306fdde03146102e45761024e565b3661024e577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706102356108e4565b346040516102449291906131af565b60405180910390a1005b600080fd5b34801561025f57600080fd5b506102686108ec565b60405161027591906131d8565b60405180910390f35b34801561028a57600080fd5b506102a560048036038101906102a0919061325f565b6108fd565b6040516102b291906132a7565b60405180910390f35b3480156102c757600080fd5b506102e260048036038101906102dd9190613332565b61090f565b005b3480156102f057600080fd5b506102f9610925565b6040516103069190613402565b60405180910390f35b34801561031b57600080fd5b5061033660048036038101906103319190613450565b6109b7565b604051610343919061347d565b60405180910390f35b34801561035857600080fd5b50610373600480360381019061036e9190613498565b6109fd565b005b34801561038157600080fd5b5061039c60048036038101906103979190613516565b610b14565b005b3480156103aa57600080fd5b506103c560048036038101906103c09190613450565b610c93565b005b3480156103d357600080fd5b506103ee60048036038101906103e99190613543565b610ca5565b005b3480156103fc57600080fd5b5061041760048036038101906104129190613596565b610d05565b6040516104259291906131af565b60405180910390f35b34801561043a57600080fd5b50610443610eef565b60405161045091906131d8565b60405180910390f35b34801561046557600080fd5b50610480600480360381019061047b9190613614565b610ef9565b60405161048d91906131d8565b60405180910390f35b3480156104a257600080fd5b506104bd60048036038101906104b89190613543565b610f80565b005b3480156104cb57600080fd5b506104e660048036038101906104e19190613614565b610fa0565b005b3480156104f457600080fd5b506104fd6111b3565b60405161050a9190613402565b60405180910390f35b34801561051f57600080fd5b5061053a60048036038101906105359190613789565b611241565b005b34801561054857600080fd5b50610563600480360381019061055e9190613450565b61125c565b604051610570919061347d565b60405180910390f35b34801561058557600080fd5b506105a0600480360381019061059b91906137d2565b6112e2565b6040516105ad91906131d8565b60405180910390f35b3480156105c257600080fd5b506105cb611399565b005b3480156105d957600080fd5b506105f460048036038101906105ef9190613450565b6113ad565b604051610601919061347d565b60405180910390f35b34801561061657600080fd5b5061061f6113f5565b60405161062c919061347d565b60405180910390f35b34801561064157600080fd5b5061064a61141f565b6040516106579190613402565b60405180910390f35b34801561066c57600080fd5b50610687600480360381019061068291906137d2565b6114b1565b60405161069491906131d8565b60405180910390f35b6106b760048036038101906106b29190613450565b6114fa565b005b3480156106c557600080fd5b506106e060048036038101906106db919061382b565b61166a565b005b3480156106ee57600080fd5b50610709600480360381019061070491906137d2565b611680565b60405161071691906131d8565b60405180910390f35b34801561072b57600080fd5b506107466004803603810190610741919061390c565b6116b3565b005b34801561075457600080fd5b5061076f600480360381019061076a9190613614565b611715565b60405161077c91906131d8565b60405180910390f35b34801561079157600080fd5b506107ac60048036038101906107a79190613450565b6117c4565b6040516107b99190613402565b60405180910390f35b3480156107ce57600080fd5b506107e960048036038101906107e491906137d2565b61182c565b6040516107f691906131d8565b60405180910390f35b34801561080b57600080fd5b506108266004803603810190610821919061398f565b611875565b60405161083391906131d8565b60405180910390f35b34801561084857600080fd5b506108516118be565b005b34801561085f57600080fd5b506108686118f2565b60405161087591906131d8565b60405180910390f35b34801561088a57600080fd5b506108a560048036038101906108a091906139bc565b6118fc565b6040516108b291906132a7565b60405180910390f35b3480156108c757600080fd5b506108e260048036038101906108dd91906137d2565b611990565b005b600033905090565b60006108f86014611a13565b905090565b600061090882611a21565b9050919050565b610917611b03565b6109218282611b81565b5050565b60606002805461093490613a2b565b80601f016020809104026020016040519081016040528092919081815260200182805461096090613a2b565b80156109ad5780601f10610982576101008083540402835291602001916109ad565b820191906000526020600020905b81548152906001019060200180831161099057829003601f168201915b5050505050905090565b60006109c282611d15565b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610a088261125c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90613ace565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a976108e4565b73ffffffffffffffffffffffffffffffffffffffff161480610ac65750610ac581610ac06108e4565b6118fc565b5b610b05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afc90613b60565b60405180910390fd5b610b0f8383611d60565b505050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8d90613bf2565b60405180910390fd5b6000610ba182611680565b905060008103610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90613c84565b60405180910390fd5b8060096000828254610bf89190613cd3565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550610c568282611e19565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568282604051610c87929190613d66565b60405180910390a15050565b610c9b611b03565b8060138190555050565b610cb6610cb06108e4565b82611f0d565b610cf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cec90613e01565b60405180910390fd5b610d00838383611fa2565b505050565b6000806000600160008681526020019081526020016000206040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1603610e9a5760006040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505090505b6000610ea461229b565b6bffffffffffffffffffffffff1682602001516bffffffffffffffffffffffff1686610ed09190613e21565b610eda9190613e92565b90508160000151819350935050509250929050565b6000600854905090565b6000600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610f9b838383604051806020016040528060008152506116b3565b505050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611022576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161101990613bf2565b60405180910390fd5b600061102e8383611715565b905060008103611073576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106a90613c84565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546110c29190613cd3565b9250508190555080600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555061115e8383836122a5565b8273ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a83836040516111a69291906131af565b60405180910390a2505050565b601580546111c090613a2b565b80601f01602080910402602001604051908101604052809291908181526020018280546111ec90613a2b565b80156112395780601f1061120e57610100808354040283529160200191611239565b820191906000526020600020905b81548152906001019060200180831161121c57829003601f168201915b505050505081565b611249611b03565b80601090816112589190614065565b5050565b6000806112688361232b565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d090614183565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611352576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134990614215565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6113a1611b03565b6113ab6000612368565b565b6000600c82815481106113c3576113c2614235565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461142e90613a2b565b80601f016020809104026020016040519081016040528092919081815260200182805461145a90613a2b565b80156114a75780601f1061147c576101008083540402835291602001916114a7565b820191906000526020600020905b81548152906001019060200180831161148a57829003601f168201915b5050505050905090565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600f60149054906101000a900460ff16611549576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611540906142b0565b60405180910390fd5b61155e8160135461242e90919063ffffffff16565b3410156115a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115979061431c565b60405180910390fd5b6012548111156115e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dc90614388565b60405180910390fd5b601154816115f36014611a13565b6115fd9190613cd3565b111561163e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116359061441a565b60405180910390fd5b60005b818110156116665761165233612444565b50808061165e9061443a565b915050611641565b5050565b61167c6116756108e4565b8383612474565b5050565b60008061168b6118f2565b476116969190613cd3565b90506116ab83826116a6866114b1565b6125e0565b915050919050565b6116c46116be6108e4565b83611f0d565b611703576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116fa90613e01565b60405180910390fd5b61170f8484848461264e565b50505050565b60008061172184611875565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161175a919061347d565b602060405180830381865afa158015611777573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179b9190614497565b6117a59190613cd3565b90506117bb83826117b68787610ef9565b6125e0565b91505092915050565b60606117cf82611d15565b60006117d96126aa565b905060008151116117f95760405180602001604052806000815250611824565b806118038461273c565b604051602001611814929190614500565b6040516020818303038152906040525b915050919050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6118c6611b03565b600f60149054906101000a900460ff1615600f60146101000a81548160ff021916908315150217905550565b6000600954905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611998611b03565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119fe90614596565b60405180910390fd5b611a1081612368565b50565b600081600001549050919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611aec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611afc5750611afb8261280a565b5b9050919050565b611b0b6108e4565b73ffffffffffffffffffffffffffffffffffffffff16611b296113f5565b73ffffffffffffffffffffffffffffffffffffffff1614611b7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7690614602565b60405180910390fd5b565b611b8961229b565b6bffffffffffffffffffffffff16816bffffffffffffffffffffffff161115611be7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bde90614694565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4d90614700565b60405180910390fd5b60405180604001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001826bffffffffffffffffffffffff168152506000808201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055509050505050565b611d1e81612884565b611d5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d5490614183565b60405180910390fd5b50565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611dd38361125c565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b80471015611e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e539061476c565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051611e82906147bd565b60006040518083038185875af1925050503d8060008114611ebf576040519150601f19603f3d011682016040523d82523d6000602084013e611ec4565b606091505b5050905080611f08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eff90614844565b60405180910390fd5b505050565b600080611f198361125c565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611f5b5750611f5a81856118fc565b5b80611f9957508373ffffffffffffffffffffffffffffffffffffffff16611f81846109b7565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611fc28261125c565b73ffffffffffffffffffffffffffffffffffffffff1614612018576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161200f906148d6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614968565b60405180910390fd5b61209483838360016128c5565b8273ffffffffffffffffffffffffffffffffffffffff166120b48261125c565b73ffffffffffffffffffffffffffffffffffffffff161461210a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612101906148d6565b60405180910390fd5b6006600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461229683838360016128cb565b505050565b6000612710905090565b6123268363a9059cbb60e01b84846040516024016122c49291906131af565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506128d1565b505050565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000818361243c9190613e21565b905092915050565b60006124506014612998565b6124638261245e6014611a13565b6129ae565b61246d6014611a13565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124d9906149d4565b60405180910390fd5b80600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125d391906132a7565b60405180910390a3505050565b600081600854600a60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054856126319190613e21565b61263b9190613e92565b61264591906149f4565b90509392505050565b612659848484611fa2565b612665848484846129cc565b6126a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269b90614a9a565b60405180910390fd5b50505050565b6060601080546126b990613a2b565b80601f01602080910402602001604051908101604052809291908181526020018280546126e590613a2b565b80156127325780601f1061270757610100808354040283529160200191612732565b820191906000526020600020905b81548152906001019060200180831161271557829003601f168201915b5050505050905090565b60606000600161274b84612b53565b01905060008167ffffffffffffffff81111561276a5761276961365e565b5b6040519080825280601f01601f19166020018201604052801561279c5781602001600182028036833780820191505090505b509050600082602001820190505b6001156127ff578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816127f3576127f2613e63565b5b049450600085036127aa575b819350505050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061287d575061287c82612ca6565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166128a68361232b565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b50505050565b50505050565b6000612933826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612d109092919063ffffffff16565b905060008151111561299357808060200190518101906129539190614acf565b612992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161298990614b6e565b60405180910390fd5b5b505050565b6001816000016000828254019250508190555050565b6129c8828260405180602001604052806000815250612d28565b5050565b60006129ed8473ffffffffffffffffffffffffffffffffffffffff16612d83565b15612b46578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a166108e4565b8786866040518563ffffffff1660e01b8152600401612a389493929190614be3565b6020604051808303816000875af1925050508015612a7457506040513d601f19601f82011682018060405250810190612a719190614c44565b60015b612af6573d8060008114612aa4576040519150601f19603f3d011682016040523d82523d6000602084013e612aa9565b606091505b506000815103612aee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae590614a9a565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612b4b565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612bb1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612ba757612ba6613e63565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612bee576d04ee2d6d415b85acef81000000008381612be457612be3613e63565b5b0492506020810190505b662386f26fc100008310612c1d57662386f26fc100008381612c1357612c12613e63565b5b0492506010810190505b6305f5e1008310612c46576305f5e1008381612c3c57612c3b613e63565b5b0492506008810190505b6127108310612c6b576127108381612c6157612c60613e63565b5b0492506004810190505b60648310612c8e5760648381612c8457612c83613e63565b5b0492506002810190505b600a8310612c9d576001810190505b80915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060612d1f8484600085612da6565b90509392505050565b612d328383612e73565b612d3f60008484846129cc565b612d7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7590614a9a565b60405180910390fd5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606082471015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290614ce3565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612e149190614d34565b60006040518083038185875af1925050503d8060008114612e51576040519150601f19603f3d011682016040523d82523d6000602084013e612e56565b606091505b5091509150612e6787838387613090565b92505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ee2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ed990614d97565b60405180910390fd5b612eeb81612884565b15612f2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f2290614e03565b60405180910390fd5b612f396000838360016128c5565b612f4281612884565b15612f82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f7990614e03565b60405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461308c6000838360016128cb565b5050565b606083156130f25760008351036130ea576130aa85612d83565b6130e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130e090614e6f565b60405180910390fd5b5b8290506130fd565b6130fc8383613105565b5b949350505050565b6000825111156131185781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161314c9190613402565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061318082613155565b9050919050565b61319081613175565b82525050565b6000819050919050565b6131a981613196565b82525050565b60006040820190506131c46000830185613187565b6131d160208301846131a0565b9392505050565b60006020820190506131ed60008301846131a0565b92915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61323c81613207565b811461324757600080fd5b50565b60008135905061325981613233565b92915050565b600060208284031215613275576132746131fd565b5b60006132838482850161324a565b91505092915050565b60008115159050919050565b6132a18161328c565b82525050565b60006020820190506132bc6000830184613298565b92915050565b6132cb81613175565b81146132d657600080fd5b50565b6000813590506132e8816132c2565b92915050565b60006bffffffffffffffffffffffff82169050919050565b61330f816132ee565b811461331a57600080fd5b50565b60008135905061332c81613306565b92915050565b60008060408385031215613349576133486131fd565b5b6000613357858286016132d9565b92505060206133688582860161331d565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156133ac578082015181840152602081019050613391565b60008484015250505050565b6000601f19601f8301169050919050565b60006133d482613372565b6133de818561337d565b93506133ee81856020860161338e565b6133f7816133b8565b840191505092915050565b6000602082019050818103600083015261341c81846133c9565b905092915050565b61342d81613196565b811461343857600080fd5b50565b60008135905061344a81613424565b92915050565b600060208284031215613466576134656131fd565b5b60006134748482850161343b565b91505092915050565b60006020820190506134926000830184613187565b92915050565b600080604083850312156134af576134ae6131fd565b5b60006134bd858286016132d9565b92505060206134ce8582860161343b565b9150509250929050565b60006134e382613155565b9050919050565b6134f3816134d8565b81146134fe57600080fd5b50565b600081359050613510816134ea565b92915050565b60006020828403121561352c5761352b6131fd565b5b600061353a84828501613501565b91505092915050565b60008060006060848603121561355c5761355b6131fd565b5b600061356a868287016132d9565b935050602061357b868287016132d9565b925050604061358c8682870161343b565b9150509250925092565b600080604083850312156135ad576135ac6131fd565b5b60006135bb8582860161343b565b92505060206135cc8582860161343b565b9150509250929050565b60006135e182613175565b9050919050565b6135f1816135d6565b81146135fc57600080fd5b50565b60008135905061360e816135e8565b92915050565b6000806040838503121561362b5761362a6131fd565b5b6000613639858286016135ff565b925050602061364a858286016132d9565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613696826133b8565b810181811067ffffffffffffffff821117156136b5576136b461365e565b5b80604052505050565b60006136c86131f3565b90506136d4828261368d565b919050565b600067ffffffffffffffff8211156136f4576136f361365e565b5b6136fd826133b8565b9050602081019050919050565b82818337600083830152505050565b600061372c613727846136d9565b6136be565b90508281526020810184848401111561374857613747613659565b5b61375384828561370a565b509392505050565b600082601f8301126137705761376f613654565b5b8135613780848260208601613719565b91505092915050565b60006020828403121561379f5761379e6131fd565b5b600082013567ffffffffffffffff8111156137bd576137bc613202565b5b6137c98482850161375b565b91505092915050565b6000602082840312156137e8576137e76131fd565b5b60006137f6848285016132d9565b91505092915050565b6138088161328c565b811461381357600080fd5b50565b600081359050613825816137ff565b92915050565b60008060408385031215613842576138416131fd565b5b6000613850858286016132d9565b925050602061386185828601613816565b9150509250929050565b600067ffffffffffffffff8211156138865761388561365e565b5b61388f826133b8565b9050602081019050919050565b60006138af6138aa8461386b565b6136be565b9050828152602081018484840111156138cb576138ca613659565b5b6138d684828561370a565b509392505050565b600082601f8301126138f3576138f2613654565b5b813561390384826020860161389c565b91505092915050565b60008060008060808587031215613926576139256131fd565b5b6000613934878288016132d9565b9450506020613945878288016132d9565b93505060406139568782880161343b565b925050606085013567ffffffffffffffff81111561397757613976613202565b5b613983878288016138de565b91505092959194509250565b6000602082840312156139a5576139a46131fd565b5b60006139b3848285016135ff565b91505092915050565b600080604083850312156139d3576139d26131fd565b5b60006139e1858286016132d9565b92505060206139f2858286016132d9565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613a4357607f821691505b602082108103613a5657613a556139fc565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ab860218361337d565b9150613ac382613a5c565b604082019050919050565b60006020820190508181036000830152613ae781613aab565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613b4a603d8361337d565b9150613b5582613aee565b604082019050919050565b60006020820190508181036000830152613b7981613b3d565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000613bdc60268361337d565b9150613be782613b80565b604082019050919050565b60006020820190508181036000830152613c0b81613bcf565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b6000613c6e602b8361337d565b9150613c7982613c12565b604082019050919050565b60006020820190508181036000830152613c9d81613c61565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613cde82613196565b9150613ce983613196565b9250828201905080821115613d0157613d00613ca4565b5b92915050565b6000819050919050565b6000613d2c613d27613d2284613155565b613d07565b613155565b9050919050565b6000613d3e82613d11565b9050919050565b6000613d5082613d33565b9050919050565b613d6081613d45565b82525050565b6000604082019050613d7b6000830185613d57565b613d8860208301846131a0565b9392505050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613deb602d8361337d565b9150613df682613d8f565b604082019050919050565b60006020820190508181036000830152613e1a81613dde565b9050919050565b6000613e2c82613196565b9150613e3783613196565b9250828202613e4581613196565b91508282048414831517613e5c57613e5b613ca4565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613e9d82613196565b9150613ea883613196565b925082613eb857613eb7613e63565b5b828204905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613f257fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613ee8565b613f2f8683613ee8565b95508019841693508086168417925050509392505050565b6000613f62613f5d613f5884613196565b613d07565b613196565b9050919050565b6000819050919050565b613f7c83613f47565b613f90613f8882613f69565b848454613ef5565b825550505050565b600090565b613fa5613f98565b613fb0818484613f73565b505050565b5b81811015613fd457613fc9600082613f9d565b600181019050613fb6565b5050565b601f82111561401957613fea81613ec3565b613ff384613ed8565b81016020851015614002578190505b61401661400e85613ed8565b830182613fb5565b50505b505050565b600082821c905092915050565b600061403c6000198460080261401e565b1980831691505092915050565b6000614055838361402b565b9150826002028217905092915050565b61406e82613372565b67ffffffffffffffff8111156140875761408661365e565b5b6140918254613a2b565b61409c828285613fd8565b600060209050601f8311600181146140cf57600084156140bd578287015190505b6140c78582614049565b86555061412f565b601f1984166140dd86613ec3565b60005b82811015614105578489015182556001820191506020850194506020810190506140e0565b86831015614122578489015161411e601f89168261402b565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061416d60188361337d565b915061417882614137565b602082019050919050565b6000602082019050818103600083015261419c81614160565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b60006141ff60298361337d565b915061420a826141a3565b604082019050919050565b6000602082019050818103600083015261422e816141f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f53616c65206973206e6f74206163746976650000000000000000000000000000600082015250565b600061429a60128361337d565b91506142a582614264565b602082019050919050565b600060208201905081810360008301526142c98161428d565b9050919050565b7f4e6f7420656e6f7567682045544820746f206d696e74204e4654530000000000600082015250565b6000614306601b8361337d565b9150614311826142d0565b602082019050919050565b60006020820190508181036000830152614335816142f9565b9050919050565b7f4578636565646564206d6178207175616e746974790000000000000000000000600082015250565b600061437260158361337d565b915061437d8261433c565b602082019050919050565b600060208201905081810360008301526143a181614365565b9050919050565b7f4578636565646564206d6178206c696d6974206f6620616c6c6f77656420746f60008201527f6b656e206d696e74730000000000000000000000000000000000000000000000602082015250565b600061440460298361337d565b915061440f826143a8565b604082019050919050565b60006020820190508181036000830152614433816143f7565b9050919050565b600061444582613196565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361447757614476613ca4565b5b600182019050919050565b60008151905061449181613424565b92915050565b6000602082840312156144ad576144ac6131fd565b5b60006144bb84828501614482565b91505092915050565b600081905092915050565b60006144da82613372565b6144e481856144c4565b93506144f481856020860161338e565b80840191505092915050565b600061450c82856144cf565b915061451882846144cf565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061458060268361337d565b915061458b82614524565b604082019050919050565b600060208201905081810360008301526145af81614573565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006145ec60208361337d565b91506145f7826145b6565b602082019050919050565b6000602082019050818103600083015261461b816145df565b9050919050565b7f455243323938313a20726f79616c7479206665652077696c6c2065786365656460008201527f2073616c65507269636500000000000000000000000000000000000000000000602082015250565b600061467e602a8361337d565b915061468982614622565b604082019050919050565b600060208201905081810360008301526146ad81614671565b9050919050565b7f455243323938313a20696e76616c696420726563656976657200000000000000600082015250565b60006146ea60198361337d565b91506146f5826146b4565b602082019050919050565b60006020820190508181036000830152614719816146dd565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000614756601d8361337d565b915061476182614720565b602082019050919050565b6000602082019050818103600083015261478581614749565b9050919050565b600081905092915050565b50565b60006147a760008361478c565b91506147b282614797565b600082019050919050565b60006147c88261479a565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b600061482e603a8361337d565b9150614839826147d2565b604082019050919050565b6000602082019050818103600083015261485d81614821565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148c060258361337d565b91506148cb82614864565b604082019050919050565b600060208201905081810360008301526148ef816148b3565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061495260248361337d565b915061495d826148f6565b604082019050919050565b6000602082019050818103600083015261498181614945565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006149be60198361337d565b91506149c982614988565b602082019050919050565b600060208201905081810360008301526149ed816149b1565b9050919050565b60006149ff82613196565b9150614a0a83613196565b9250828203905081811115614a2257614a21613ca4565b5b92915050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614a8460328361337d565b9150614a8f82614a28565b604082019050919050565b60006020820190508181036000830152614ab381614a77565b9050919050565b600081519050614ac9816137ff565b92915050565b600060208284031215614ae557614ae46131fd565b5b6000614af384828501614aba565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614b58602a8361337d565b9150614b6382614afc565b604082019050919050565b60006020820190508181036000830152614b8781614b4b565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614bb582614b8e565b614bbf8185614b99565b9350614bcf81856020860161338e565b614bd8816133b8565b840191505092915050565b6000608082019050614bf86000830187613187565b614c056020830186613187565b614c1260408301856131a0565b8181036060830152614c248184614baa565b905095945050505050565b600081519050614c3e81613233565b92915050565b600060208284031215614c5a57614c596131fd565b5b6000614c6884828501614c2f565b91505092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614ccd60268361337d565b9150614cd882614c71565b604082019050919050565b60006020820190508181036000830152614cfc81614cc0565b9050919050565b6000614d0e82614b8e565b614d18818561478c565b9350614d2881856020860161338e565b80840191505092915050565b6000614d408284614d03565b915081905092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614d8160208361337d565b9150614d8c82614d4b565b602082019050919050565b60006020820190508181036000830152614db081614d74565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614ded601c8361337d565b9150614df882614db7565b602082019050919050565b60006020820190508181036000830152614e1c81614de0565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e59601d8361337d565b9150614e6482614e23565b602082019050919050565b60006020820190508181036000830152614e8881614e4c565b905091905056fea264697066735822122068bfe64318c971a745d98b1ef7fb8204df6d1f9b9ec196713ca418767167f2dd64736f6c634300081200333237303565326639336162613239396564383930323034663033666430316435366631366135626132636563303439326434623032643530366233356462636368747470733a2f2f6d657461646174612e6d6f6e7374657266616e636c75622e6e65742f6d666330312f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000ec330f4b3e1e4dc2d30c17034a406978b10d3ec00000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b33edfd0397d3cc7eaac77d773516bd04a0a6d22000000000000000000000000b327958b7e03028638da98215a1cd7088dc88bc00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000046
Deployed Bytecode
0x6080604052600436106102075760003560e01c806370a0823111610118578063b88d4fde116100a0578063d79779b21161006f578063d79779b2146107ff578063daaeec861461083c578063e33b7de314610853578063e985e9c51461087e578063f2fde38b146108bb5761024e565b8063b88d4fde1461071f578063c45ac05014610748578063c87b56dd14610785578063ce7c2ac2146107c25761024e565b806395d89b41116100e757806395d89b41146106355780639852595c14610660578063a0712d681461069d578063a22cb465146106b9578063a3f8eace146106e25761024e565b806370a0823114610579578063715018a6146105b65780638b83209b146105cd5780638da5cb5b1461060a5761024e565b806323b872dd1161019b57806342842e0e1161016a57806342842e0e1461049657806348b75044146104bf57806351605d80146104e857806355f804b3146105135780636352211e1461053c5761024e565b806323b872dd146103c75780632a55205a146103f05780633a98ef391461042e578063406072a9146104595761024e565b8063081812fc116101d7578063081812fc1461030f578063095ea7b31461034c57806319165587146103755780631919fed71461039e5761024e565b80629a9b7b1461025357806301ffc9a71461027e57806304634d8d146102bb57806306fdde03146102e45761024e565b3661024e577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706102356108e4565b346040516102449291906131af565b60405180910390a1005b600080fd5b34801561025f57600080fd5b506102686108ec565b60405161027591906131d8565b60405180910390f35b34801561028a57600080fd5b506102a560048036038101906102a0919061325f565b6108fd565b6040516102b291906132a7565b60405180910390f35b3480156102c757600080fd5b506102e260048036038101906102dd9190613332565b61090f565b005b3480156102f057600080fd5b506102f9610925565b6040516103069190613402565b60405180910390f35b34801561031b57600080fd5b5061033660048036038101906103319190613450565b6109b7565b604051610343919061347d565b60405180910390f35b34801561035857600080fd5b50610373600480360381019061036e9190613498565b6109fd565b005b34801561038157600080fd5b5061039c60048036038101906103979190613516565b610b14565b005b3480156103aa57600080fd5b506103c560048036038101906103c09190613450565b610c93565b005b3480156103d357600080fd5b506103ee60048036038101906103e99190613543565b610ca5565b005b3480156103fc57600080fd5b5061041760048036038101906104129190613596565b610d05565b6040516104259291906131af565b60405180910390f35b34801561043a57600080fd5b50610443610eef565b60405161045091906131d8565b60405180910390f35b34801561046557600080fd5b50610480600480360381019061047b9190613614565b610ef9565b60405161048d91906131d8565b60405180910390f35b3480156104a257600080fd5b506104bd60048036038101906104b89190613543565b610f80565b005b3480156104cb57600080fd5b506104e660048036038101906104e19190613614565b610fa0565b005b3480156104f457600080fd5b506104fd6111b3565b60405161050a9190613402565b60405180910390f35b34801561051f57600080fd5b5061053a60048036038101906105359190613789565b611241565b005b34801561054857600080fd5b50610563600480360381019061055e9190613450565b61125c565b604051610570919061347d565b60405180910390f35b34801561058557600080fd5b506105a0600480360381019061059b91906137d2565b6112e2565b6040516105ad91906131d8565b60405180910390f35b3480156105c257600080fd5b506105cb611399565b005b3480156105d957600080fd5b506105f460048036038101906105ef9190613450565b6113ad565b604051610601919061347d565b60405180910390f35b34801561061657600080fd5b5061061f6113f5565b60405161062c919061347d565b60405180910390f35b34801561064157600080fd5b5061064a61141f565b6040516106579190613402565b60405180910390f35b34801561066c57600080fd5b50610687600480360381019061068291906137d2565b6114b1565b60405161069491906131d8565b60405180910390f35b6106b760048036038101906106b29190613450565b6114fa565b005b3480156106c557600080fd5b506106e060048036038101906106db919061382b565b61166a565b005b3480156106ee57600080fd5b50610709600480360381019061070491906137d2565b611680565b60405161071691906131d8565b60405180910390f35b34801561072b57600080fd5b506107466004803603810190610741919061390c565b6116b3565b005b34801561075457600080fd5b5061076f600480360381019061076a9190613614565b611715565b60405161077c91906131d8565b60405180910390f35b34801561079157600080fd5b506107ac60048036038101906107a79190613450565b6117c4565b6040516107b99190613402565b60405180910390f35b3480156107ce57600080fd5b506107e960048036038101906107e491906137d2565b61182c565b6040516107f691906131d8565b60405180910390f35b34801561080b57600080fd5b506108266004803603810190610821919061398f565b611875565b60405161083391906131d8565b60405180910390f35b34801561084857600080fd5b506108516118be565b005b34801561085f57600080fd5b506108686118f2565b60405161087591906131d8565b60405180910390f35b34801561088a57600080fd5b506108a560048036038101906108a091906139bc565b6118fc565b6040516108b291906132a7565b60405180910390f35b3480156108c757600080fd5b506108e260048036038101906108dd91906137d2565b611990565b005b600033905090565b60006108f86014611a13565b905090565b600061090882611a21565b9050919050565b610917611b03565b6109218282611b81565b5050565b60606002805461093490613a2b565b80601f016020809104026020016040519081016040528092919081815260200182805461096090613a2b565b80156109ad5780601f10610982576101008083540402835291602001916109ad565b820191906000526020600020905b81548152906001019060200180831161099057829003601f168201915b5050505050905090565b60006109c282611d15565b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610a088261125c565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90613ace565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a976108e4565b73ffffffffffffffffffffffffffffffffffffffff161480610ac65750610ac581610ac06108e4565b6118fc565b5b610b05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afc90613b60565b60405180910390fd5b610b0f8383611d60565b505050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8d90613bf2565b60405180910390fd5b6000610ba182611680565b905060008103610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90613c84565b60405180910390fd5b8060096000828254610bf89190613cd3565b9250508190555080600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550610c568282611e19565b7fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b0568282604051610c87929190613d66565b60405180910390a15050565b610c9b611b03565b8060138190555050565b610cb6610cb06108e4565b82611f0d565b610cf5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cec90613e01565b60405180910390fd5b610d00838383611fa2565b505050565b6000806000600160008681526020019081526020016000206040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1603610e9a5760006040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff168152505090505b6000610ea461229b565b6bffffffffffffffffffffffff1682602001516bffffffffffffffffffffffff1686610ed09190613e21565b610eda9190613e92565b90508160000151819350935050509250929050565b6000600854905090565b6000600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610f9b838383604051806020016040528060008152506116b3565b505050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411611022576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161101990613bf2565b60405180910390fd5b600061102e8383611715565b905060008103611073576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106a90613c84565b60405180910390fd5b80600d60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546110c29190613cd3565b9250508190555080600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555061115e8383836122a5565b8273ffffffffffffffffffffffffffffffffffffffff167f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a83836040516111a69291906131af565b60405180910390a2505050565b601580546111c090613a2b565b80601f01602080910402602001604051908101604052809291908181526020018280546111ec90613a2b565b80156112395780601f1061120e57610100808354040283529160200191611239565b820191906000526020600020905b81548152906001019060200180831161121c57829003601f168201915b505050505081565b611249611b03565b80601090816112589190614065565b5050565b6000806112688361232b565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036112d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d090614183565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611352576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134990614215565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6113a1611b03565b6113ab6000612368565b565b6000600c82815481106113c3576113c2614235565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461142e90613a2b565b80601f016020809104026020016040519081016040528092919081815260200182805461145a90613a2b565b80156114a75780601f1061147c576101008083540402835291602001916114a7565b820191906000526020600020905b81548152906001019060200180831161148a57829003601f168201915b5050505050905090565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600f60149054906101000a900460ff16611549576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611540906142b0565b60405180910390fd5b61155e8160135461242e90919063ffffffff16565b3410156115a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115979061431c565b60405180910390fd5b6012548111156115e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115dc90614388565b60405180910390fd5b601154816115f36014611a13565b6115fd9190613cd3565b111561163e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116359061441a565b60405180910390fd5b60005b818110156116665761165233612444565b50808061165e9061443a565b915050611641565b5050565b61167c6116756108e4565b8383612474565b5050565b60008061168b6118f2565b476116969190613cd3565b90506116ab83826116a6866114b1565b6125e0565b915050919050565b6116c46116be6108e4565b83611f0d565b611703576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116fa90613e01565b60405180910390fd5b61170f8484848461264e565b50505050565b60008061172184611875565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161175a919061347d565b602060405180830381865afa158015611777573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179b9190614497565b6117a59190613cd3565b90506117bb83826117b68787610ef9565b6125e0565b91505092915050565b60606117cf82611d15565b60006117d96126aa565b905060008151116117f95760405180602001604052806000815250611824565b806118038461273c565b604051602001611814929190614500565b6040516020818303038152906040525b915050919050565b6000600a60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6118c6611b03565b600f60149054906101000a900460ff1615600f60146101000a81548160ff021916908315150217905550565b6000600954905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b611998611b03565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119fe90614596565b60405180910390fd5b611a1081612368565b50565b600081600001549050919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611aec57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611afc5750611afb8261280a565b5b9050919050565b611b0b6108e4565b73ffffffffffffffffffffffffffffffffffffffff16611b296113f5565b73ffffffffffffffffffffffffffffffffffffffff1614611b7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7690614602565b60405180910390fd5b565b611b8961229b565b6bffffffffffffffffffffffff16816bffffffffffffffffffffffff161115611be7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bde90614694565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611c56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4d90614700565b60405180910390fd5b60405180604001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001826bffffffffffffffffffffffff168152506000808201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055509050505050565b611d1e81612884565b611d5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d5490614183565b60405180910390fd5b50565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611dd38361125c565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b80471015611e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e539061476c565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff1682604051611e82906147bd565b60006040518083038185875af1925050503d8060008114611ebf576040519150601f19603f3d011682016040523d82523d6000602084013e611ec4565b606091505b5050905080611f08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eff90614844565b60405180910390fd5b505050565b600080611f198361125c565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611f5b5750611f5a81856118fc565b5b80611f9957508373ffffffffffffffffffffffffffffffffffffffff16611f81846109b7565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611fc28261125c565b73ffffffffffffffffffffffffffffffffffffffff1614612018576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161200f906148d6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614968565b60405180910390fd5b61209483838360016128c5565b8273ffffffffffffffffffffffffffffffffffffffff166120b48261125c565b73ffffffffffffffffffffffffffffffffffffffff161461210a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612101906148d6565b60405180910390fd5b6006600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461229683838360016128cb565b505050565b6000612710905090565b6123268363a9059cbb60e01b84846040516024016122c49291906131af565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506128d1565b505050565b60006004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000818361243c9190613e21565b905092915050565b60006124506014612998565b6124638261245e6014611a13565b6129ae565b61246d6014611a13565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124d9906149d4565b60405180910390fd5b80600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125d391906132a7565b60405180910390a3505050565b600081600854600a60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054856126319190613e21565b61263b9190613e92565b61264591906149f4565b90509392505050565b612659848484611fa2565b612665848484846129cc565b6126a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161269b90614a9a565b60405180910390fd5b50505050565b6060601080546126b990613a2b565b80601f01602080910402602001604051908101604052809291908181526020018280546126e590613a2b565b80156127325780601f1061270757610100808354040283529160200191612732565b820191906000526020600020905b81548152906001019060200180831161271557829003601f168201915b5050505050905090565b60606000600161274b84612b53565b01905060008167ffffffffffffffff81111561276a5761276961365e565b5b6040519080825280601f01601f19166020018201604052801561279c5781602001600182028036833780820191505090505b509050600082602001820190505b6001156127ff578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816127f3576127f2613e63565b5b049450600085036127aa575b819350505050919050565b60007f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061287d575061287c82612ca6565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166128a68361232b565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b50505050565b50505050565b6000612933826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612d109092919063ffffffff16565b905060008151111561299357808060200190518101906129539190614acf565b612992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161298990614b6e565b60405180910390fd5b5b505050565b6001816000016000828254019250508190555050565b6129c8828260405180602001604052806000815250612d28565b5050565b60006129ed8473ffffffffffffffffffffffffffffffffffffffff16612d83565b15612b46578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a166108e4565b8786866040518563ffffffff1660e01b8152600401612a389493929190614be3565b6020604051808303816000875af1925050508015612a7457506040513d601f19601f82011682018060405250810190612a719190614c44565b60015b612af6573d8060008114612aa4576040519150601f19603f3d011682016040523d82523d6000602084013e612aa9565b606091505b506000815103612aee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae590614a9a565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612b4b565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612bb1577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612ba757612ba6613e63565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612bee576d04ee2d6d415b85acef81000000008381612be457612be3613e63565b5b0492506020810190505b662386f26fc100008310612c1d57662386f26fc100008381612c1357612c12613e63565b5b0492506010810190505b6305f5e1008310612c46576305f5e1008381612c3c57612c3b613e63565b5b0492506008810190505b6127108310612c6b576127108381612c6157612c60613e63565b5b0492506004810190505b60648310612c8e5760648381612c8457612c83613e63565b5b0492506002810190505b600a8310612c9d576001810190505b80915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060612d1f8484600085612da6565b90509392505050565b612d328383612e73565b612d3f60008484846129cc565b612d7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d7590614a9a565b60405180910390fd5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b606082471015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290614ce3565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612e149190614d34565b60006040518083038185875af1925050503d8060008114612e51576040519150601f19603f3d011682016040523d82523d6000602084013e612e56565b606091505b5091509150612e6787838387613090565b92505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ee2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ed990614d97565b60405180910390fd5b612eeb81612884565b15612f2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f2290614e03565b60405180910390fd5b612f396000838360016128c5565b612f4281612884565b15612f82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f7990614e03565b60405180910390fd5b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461308c6000838360016128cb565b5050565b606083156130f25760008351036130ea576130aa85612d83565b6130e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130e090614e6f565b60405180910390fd5b5b8290506130fd565b6130fc8383613105565b5b949350505050565b6000825111156131185781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161314c9190613402565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061318082613155565b9050919050565b61319081613175565b82525050565b6000819050919050565b6131a981613196565b82525050565b60006040820190506131c46000830185613187565b6131d160208301846131a0565b9392505050565b60006020820190506131ed60008301846131a0565b92915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61323c81613207565b811461324757600080fd5b50565b60008135905061325981613233565b92915050565b600060208284031215613275576132746131fd565b5b60006132838482850161324a565b91505092915050565b60008115159050919050565b6132a18161328c565b82525050565b60006020820190506132bc6000830184613298565b92915050565b6132cb81613175565b81146132d657600080fd5b50565b6000813590506132e8816132c2565b92915050565b60006bffffffffffffffffffffffff82169050919050565b61330f816132ee565b811461331a57600080fd5b50565b60008135905061332c81613306565b92915050565b60008060408385031215613349576133486131fd565b5b6000613357858286016132d9565b92505060206133688582860161331d565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156133ac578082015181840152602081019050613391565b60008484015250505050565b6000601f19601f8301169050919050565b60006133d482613372565b6133de818561337d565b93506133ee81856020860161338e565b6133f7816133b8565b840191505092915050565b6000602082019050818103600083015261341c81846133c9565b905092915050565b61342d81613196565b811461343857600080fd5b50565b60008135905061344a81613424565b92915050565b600060208284031215613466576134656131fd565b5b60006134748482850161343b565b91505092915050565b60006020820190506134926000830184613187565b92915050565b600080604083850312156134af576134ae6131fd565b5b60006134bd858286016132d9565b92505060206134ce8582860161343b565b9150509250929050565b60006134e382613155565b9050919050565b6134f3816134d8565b81146134fe57600080fd5b50565b600081359050613510816134ea565b92915050565b60006020828403121561352c5761352b6131fd565b5b600061353a84828501613501565b91505092915050565b60008060006060848603121561355c5761355b6131fd565b5b600061356a868287016132d9565b935050602061357b868287016132d9565b925050604061358c8682870161343b565b9150509250925092565b600080604083850312156135ad576135ac6131fd565b5b60006135bb8582860161343b565b92505060206135cc8582860161343b565b9150509250929050565b60006135e182613175565b9050919050565b6135f1816135d6565b81146135fc57600080fd5b50565b60008135905061360e816135e8565b92915050565b6000806040838503121561362b5761362a6131fd565b5b6000613639858286016135ff565b925050602061364a858286016132d9565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613696826133b8565b810181811067ffffffffffffffff821117156136b5576136b461365e565b5b80604052505050565b60006136c86131f3565b90506136d4828261368d565b919050565b600067ffffffffffffffff8211156136f4576136f361365e565b5b6136fd826133b8565b9050602081019050919050565b82818337600083830152505050565b600061372c613727846136d9565b6136be565b90508281526020810184848401111561374857613747613659565b5b61375384828561370a565b509392505050565b600082601f8301126137705761376f613654565b5b8135613780848260208601613719565b91505092915050565b60006020828403121561379f5761379e6131fd565b5b600082013567ffffffffffffffff8111156137bd576137bc613202565b5b6137c98482850161375b565b91505092915050565b6000602082840312156137e8576137e76131fd565b5b60006137f6848285016132d9565b91505092915050565b6138088161328c565b811461381357600080fd5b50565b600081359050613825816137ff565b92915050565b60008060408385031215613842576138416131fd565b5b6000613850858286016132d9565b925050602061386185828601613816565b9150509250929050565b600067ffffffffffffffff8211156138865761388561365e565b5b61388f826133b8565b9050602081019050919050565b60006138af6138aa8461386b565b6136be565b9050828152602081018484840111156138cb576138ca613659565b5b6138d684828561370a565b509392505050565b600082601f8301126138f3576138f2613654565b5b813561390384826020860161389c565b91505092915050565b60008060008060808587031215613926576139256131fd565b5b6000613934878288016132d9565b9450506020613945878288016132d9565b93505060406139568782880161343b565b925050606085013567ffffffffffffffff81111561397757613976613202565b5b613983878288016138de565b91505092959194509250565b6000602082840312156139a5576139a46131fd565b5b60006139b3848285016135ff565b91505092915050565b600080604083850312156139d3576139d26131fd565b5b60006139e1858286016132d9565b92505060206139f2858286016132d9565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613a4357607f821691505b602082108103613a5657613a556139fc565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ab860218361337d565b9150613ac382613a5c565b604082019050919050565b60006020820190508181036000830152613ae781613aab565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613b4a603d8361337d565b9150613b5582613aee565b604082019050919050565b60006020820190508181036000830152613b7981613b3d565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060008201527f7368617265730000000000000000000000000000000000000000000000000000602082015250565b6000613bdc60268361337d565b9150613be782613b80565b604082019050919050565b60006020820190508181036000830152613c0b81613bcf565b9050919050565b7f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060008201527f647565207061796d656e74000000000000000000000000000000000000000000602082015250565b6000613c6e602b8361337d565b9150613c7982613c12565b604082019050919050565b60006020820190508181036000830152613c9d81613c61565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613cde82613196565b9150613ce983613196565b9250828201905080821115613d0157613d00613ca4565b5b92915050565b6000819050919050565b6000613d2c613d27613d2284613155565b613d07565b613155565b9050919050565b6000613d3e82613d11565b9050919050565b6000613d5082613d33565b9050919050565b613d6081613d45565b82525050565b6000604082019050613d7b6000830185613d57565b613d8860208301846131a0565b9392505050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613deb602d8361337d565b9150613df682613d8f565b604082019050919050565b60006020820190508181036000830152613e1a81613dde565b9050919050565b6000613e2c82613196565b9150613e3783613196565b9250828202613e4581613196565b91508282048414831517613e5c57613e5b613ca4565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613e9d82613196565b9150613ea883613196565b925082613eb857613eb7613e63565b5b828204905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613f257fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613ee8565b613f2f8683613ee8565b95508019841693508086168417925050509392505050565b6000613f62613f5d613f5884613196565b613d07565b613196565b9050919050565b6000819050919050565b613f7c83613f47565b613f90613f8882613f69565b848454613ef5565b825550505050565b600090565b613fa5613f98565b613fb0818484613f73565b505050565b5b81811015613fd457613fc9600082613f9d565b600181019050613fb6565b5050565b601f82111561401957613fea81613ec3565b613ff384613ed8565b81016020851015614002578190505b61401661400e85613ed8565b830182613fb5565b50505b505050565b600082821c905092915050565b600061403c6000198460080261401e565b1980831691505092915050565b6000614055838361402b565b9150826002028217905092915050565b61406e82613372565b67ffffffffffffffff8111156140875761408661365e565b5b6140918254613a2b565b61409c828285613fd8565b600060209050601f8311600181146140cf57600084156140bd578287015190505b6140c78582614049565b86555061412f565b601f1984166140dd86613ec3565b60005b82811015614105578489015182556001820191506020850194506020810190506140e0565b86831015614122578489015161411e601f89168261402b565b8355505b6001600288020188555050505b505050505050565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061416d60188361337d565b915061417882614137565b602082019050919050565b6000602082019050818103600083015261419c81614160565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b60006141ff60298361337d565b915061420a826141a3565b604082019050919050565b6000602082019050818103600083015261422e816141f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f53616c65206973206e6f74206163746976650000000000000000000000000000600082015250565b600061429a60128361337d565b91506142a582614264565b602082019050919050565b600060208201905081810360008301526142c98161428d565b9050919050565b7f4e6f7420656e6f7567682045544820746f206d696e74204e4654530000000000600082015250565b6000614306601b8361337d565b9150614311826142d0565b602082019050919050565b60006020820190508181036000830152614335816142f9565b9050919050565b7f4578636565646564206d6178207175616e746974790000000000000000000000600082015250565b600061437260158361337d565b915061437d8261433c565b602082019050919050565b600060208201905081810360008301526143a181614365565b9050919050565b7f4578636565646564206d6178206c696d6974206f6620616c6c6f77656420746f60008201527f6b656e206d696e74730000000000000000000000000000000000000000000000602082015250565b600061440460298361337d565b915061440f826143a8565b604082019050919050565b60006020820190508181036000830152614433816143f7565b9050919050565b600061444582613196565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361447757614476613ca4565b5b600182019050919050565b60008151905061449181613424565b92915050565b6000602082840312156144ad576144ac6131fd565b5b60006144bb84828501614482565b91505092915050565b600081905092915050565b60006144da82613372565b6144e481856144c4565b93506144f481856020860161338e565b80840191505092915050565b600061450c82856144cf565b915061451882846144cf565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061458060268361337d565b915061458b82614524565b604082019050919050565b600060208201905081810360008301526145af81614573565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006145ec60208361337d565b91506145f7826145b6565b602082019050919050565b6000602082019050818103600083015261461b816145df565b9050919050565b7f455243323938313a20726f79616c7479206665652077696c6c2065786365656460008201527f2073616c65507269636500000000000000000000000000000000000000000000602082015250565b600061467e602a8361337d565b915061468982614622565b604082019050919050565b600060208201905081810360008301526146ad81614671565b9050919050565b7f455243323938313a20696e76616c696420726563656976657200000000000000600082015250565b60006146ea60198361337d565b91506146f5826146b4565b602082019050919050565b60006020820190508181036000830152614719816146dd565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b6000614756601d8361337d565b915061476182614720565b602082019050919050565b6000602082019050818103600083015261478581614749565b9050919050565b600081905092915050565b50565b60006147a760008361478c565b91506147b282614797565b600082019050919050565b60006147c88261479a565b9150819050919050565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b600061482e603a8361337d565b9150614839826147d2565b604082019050919050565b6000602082019050818103600083015261485d81614821565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006148c060258361337d565b91506148cb82614864565b604082019050919050565b600060208201905081810360008301526148ef816148b3565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b600061495260248361337d565b915061495d826148f6565b604082019050919050565b6000602082019050818103600083015261498181614945565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b60006149be60198361337d565b91506149c982614988565b602082019050919050565b600060208201905081810360008301526149ed816149b1565b9050919050565b60006149ff82613196565b9150614a0a83613196565b9250828203905081811115614a2257614a21613ca4565b5b92915050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614a8460328361337d565b9150614a8f82614a28565b604082019050919050565b60006020820190508181036000830152614ab381614a77565b9050919050565b600081519050614ac9816137ff565b92915050565b600060208284031215614ae557614ae46131fd565b5b6000614af384828501614aba565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614b58602a8361337d565b9150614b6382614afc565b604082019050919050565b60006020820190508181036000830152614b8781614b4b565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000614bb582614b8e565b614bbf8185614b99565b9350614bcf81856020860161338e565b614bd8816133b8565b840191505092915050565b6000608082019050614bf86000830187613187565b614c056020830186613187565b614c1260408301856131a0565b8181036060830152614c248184614baa565b905095945050505050565b600081519050614c3e81613233565b92915050565b600060208284031215614c5a57614c596131fd565b5b6000614c6884828501614c2f565b91505092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000614ccd60268361337d565b9150614cd882614c71565b604082019050919050565b60006020820190508181036000830152614cfc81614cc0565b9050919050565b6000614d0e82614b8e565b614d18818561478c565b9350614d2881856020860161338e565b80840191505092915050565b6000614d408284614d03565b915081905092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614d8160208361337d565b9150614d8c82614d4b565b602082019050919050565b60006020820190508181036000830152614db081614d74565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614ded601c8361337d565b9150614df882614db7565b602082019050919050565b60006020820190508181036000830152614e1c81614de0565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614e59601d8361337d565b9150614e6482614e23565b602082019050919050565b60006020820190508181036000830152614e8881614e4c565b905091905056fea264697066735822122068bfe64318c971a745d98b1ef7fb8204df6d1f9b9ec196713ca418767167f2dd64736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000ec330f4b3e1e4dc2d30c17034a406978b10d3ec00000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b33edfd0397d3cc7eaac77d773516bd04a0a6d22000000000000000000000000b327958b7e03028638da98215a1cd7088dc88bc00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000046
-----Decoded View---------------
Arg [0] : payees (address[]): 0xb33edFd0397D3cC7EAac77d773516bd04A0A6d22,0xb327958b7e03028638Da98215A1cd7088DC88BC0
Arg [1] : shares (uint256[]): 30,70
Arg [2] : royaltiesReceiver (address): 0x0ec330F4B3E1E4dC2d30C17034a406978b10d3eC
Arg [3] : royaltiesFeeNumerator (uint96): 600
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000ec330f4b3e1e4dc2d30c17034a406978b10d3ec
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 000000000000000000000000b33edfd0397d3cc7eaac77d773516bd04a0a6d22
Arg [6] : 000000000000000000000000b327958b7e03028638da98215a1cd7088dc88bc0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [8] : 000000000000000000000000000000000000000000000000000000000000001e
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000046
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.