Source Code
Overview
APE Balance
APE Value
$0.00Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NftStake
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import "./ReentrancyGuardUpgradeable.sol";
import "./SafeMathUpgradeable.sol";
import "./SafeERC20Upgradeable.sol";
import "./ECDSAUpgradeable.sol";
/**
* @title Paddlefi's NftStake Contract
* @author Paddlefi
*/
contract NftStake is OwnableUpgradeable, ReentrancyGuardUpgradeable {
using SafeMathUpgradeable for uint256;
using SafeERC20Upgradeable for IERC20Upgradeable;
using ECDSAUpgradeable for bytes32;
// keccak256("Asset(address token,uint256 amount,uint256 withdrawed)")
bytes32 public ASSET_HASH;
// keccak256("Order(Asset[] asset,uint256 deadline)")
bytes32 public ORDER_HASH;
// use for EIP712
bytes32 public DOMAIN_SEPARATOR;
// signer of order to claim
address public signer;
/**
* @notice Asset info
* @member token collection address
* @member amount amount to withdraw
* @member withdrawed total withdrawed amount until now
*/
struct Asset{
address token;
uint256 amount;
uint256 withdrawed;
}
/**
* @notice Order info
* @member user
* @member asset asset list
* @member deadline deadline in timestamp - 0 for no expiry
* @member sig Signature
*/
struct Order {
address user;
uint256 deadline;
Asset[] asset;
bytes sig;
}
/// @notice user => token => withdrawed amount
mapping(address => mapping(address => uint256)) public withdrawedAmount;
// stake address
address public stakeToken;
// min stake amount
uint256 public minStakeAmount;
/// @notice user => staked amount
mapping(address => uint256) public stakedAmount;
event Stake(address user, address token, uint256 amount);
event UnStake(address user, address token, uint256 amount);
event Claim(address user, address token, uint256 amount, uint256 totalAmount);
/**
* @notice Initialize contract parameters - only execute once
* @param owner_ Owner address
* @param signer_ order sign address
* @param stakeToken_ stake ptoken address
* @param minStakeAmount_ stake ptoken amount
*/
function initialize(address owner_,address signer_,address stakeToken_,uint256 minStakeAmount_) external initializer {
_transferOwnership(owner_);
__ReentrancyGuard_init();
signer = signer_;
stakeToken = stakeToken_;
minStakeAmount = minStakeAmount_;
ASSET_HASH = keccak256("Asset(address token,uint256 amount,uint256 withdrawed)");
ORDER_HASH = keccak256("Order(address user,uint256 deadline,Asset[] asset)Asset(address token,uint256 amount,uint256 withdrawed)");
uint256 chainId;
assembly {
chainId := chainid()
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes("NftStake")),
keccak256(bytes("1")),
chainId,
address(this)
)
);
}
receive() external payable {}
/**
* @notice update
* @param signer_ order sign address
* @param stakeToken_ stake ptoken address
* @param minStakeAmount_ stake ptoken amount
*/
function update(address signer_,address stakeToken_,uint256 minStakeAmount_) external onlyOwner {
signer = signer_;
stakeToken = stakeToken_;
minStakeAmount = minStakeAmount_;
}
function stake() payable public nonReentrant {
address user = msg.sender;
require(minStakeAmount > 0,"minStake");
require(stakedAmount[user] < minStakeAmount,"amount");
stakedAmount[user] = stakedAmount[user].add(minStakeAmount);
if(stakeToken == address(1)){
require(msg.value >= minStakeAmount,"value");
if(msg.value > minStakeAmount){
payable(user).transfer(msg.value - minStakeAmount);
}
}else{
IERC20Upgradeable(stakeToken).safeTransferFrom(user,address(this),minStakeAmount);
}
emit Stake(user, stakeToken, stakedAmount[user]);
}
function unstake() public nonReentrant {
address user = msg.sender;
uint256 stakeAmount = stakedAmount[user];
require(stakeAmount > 0,"amount");
stakedAmount[user] = 0;
if(stakeToken == address(1)){
payable(user).transfer(stakeAmount);
}else{
IERC20Upgradeable(stakeToken).safeTransfer(user,stakeAmount);
}
emit UnStake(user, stakeToken, stakeAmount);
}
/**
* @notice claim confirms the order by checking seller's signature
* @param order_ Seller order info
*/
function claim(Order calldata order_) public nonReentrant {
_validate(order_);
for(uint i=0;i<order_.asset.length;i++){
require(order_.asset[i].token != address(0),"token");
require(order_.asset[i].amount > 0,"amount");
uint256 last = withdrawedAmount[order_.user][order_.asset[i].token];
require(order_.asset[i].withdrawed == last ,"withdrawed");
uint256 total = last.add(order_.asset[i].amount);
withdrawedAmount[order_.user][order_.asset[i].token] = total;
if(order_.asset[i].token == address(1)){
payable(order_.user).transfer(order_.asset[i].amount);
}else{
IERC20Upgradeable(order_.asset[i].token).safeTransfer(order_.user,order_.asset[i].amount);
}
emit Claim(order_.user, order_.asset[i].token, order_.asset[i].amount, total);
}
}
/**
* @notice Get hash of order information
* @param assets Order info
* @return assetsHash order hash
*/
function _packAsset(Asset[] calldata assets) internal view returns (bytes32) {
bytes32[] memory assetHashes = new bytes32[](assets.length);
uint256 assetsLength = assets.length;
for (uint256 i; i < assetsLength; ) {
assetHashes[i] = keccak256(abi.encode(ASSET_HASH, assets[i].token, assets[i].amount,assets[i].withdrawed));
unchecked {
++i;
}
}
return keccak256(abi.encodePacked(assetHashes));
}
/**
* @notice Get hash of order information
* @param order Order info
* @return orderHash order hash
*/
function hashOrder(Order calldata order) public view returns (bytes32 orderHash) {
bytes32 structHash = keccak256(abi.encode(
ORDER_HASH,
order.user,
order.deadline,
_packAsset(order.asset)
));
orderHash = keccak256( abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, structHash) );
}
/**
* @notice Signature validation
* @param order Order info
* @return digest Order info hash
*/
function _validate(Order calldata order) internal view returns (bytes32 digest) {
require(order.user == msg.sender,"user");
require(order.deadline >= block.timestamp, "deadline");
require(order.asset.length > 0, "asset");
digest = hashOrder(order);
address newSigner = digest.recover(order.sig);
require(newSigner != address(0) && signer == newSigner, "sig");
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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.8.0/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.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
import {Initializable} from "./Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "./StringsUpgradeable.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20PermitUpgradeable {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
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.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "./AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
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) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 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 256, 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 << 3) < value ? 1 : 0);
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "./ContextUpgradeable.sol";
import {Initializable} from "./Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import {Initializable} from "./Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
import "./IERC20PermitUpgradeable.sol";
import "./AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20PermitUpgradeable token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {
// 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 cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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 SafeMathUpgradeable {
/**
* @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/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMathUpgradeable {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./MathUpgradeable.sol";
import "./SignedMathUpgradeable.sol";
/**
* @dev String operations.
*/
library StringsUpgradeable {
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 = MathUpgradeable.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 `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, MathUpgradeable.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);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnStake","type":"event"},{"inputs":[],"name":"ASSET_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORDER_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"withdrawed","type":"uint256"}],"internalType":"struct NftStake.Asset[]","name":"asset","type":"tuple[]"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct NftStake.Order","name":"order_","type":"tuple"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"withdrawed","type":"uint256"}],"internalType":"struct NftStake.Asset[]","name":"asset","type":"tuple[]"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct NftStake.Order","name":"order","type":"tuple"}],"name":"hashOrder","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"signer_","type":"address"},{"internalType":"address","name":"stakeToken_","type":"address"},{"internalType":"uint256","name":"minStakeAmount_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minStakeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"stakeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer_","type":"address"},{"internalType":"address","name":"stakeToken_","type":"address"},{"internalType":"uint256","name":"minStakeAmount_","type":"uint256"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"withdrawedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b50611c61806100206000396000f3fe6080604052600436106101025760003560e01c806374e2ce4411610095578063cf756fdf11610064578063cf756fdf1461026d578063e57c2c111461028d578063f1887684146102c5578063f2fde38b146102db578063f9931855146102fb57600080fd5b806374e2ce44146101ef5780638ce516da1461020f5780638da5cb5b1461022f578063be164af31461024d57600080fd5b80633a4b66f1116100d15780633a4b66f11461019c57806351ed6a30146101a4578063661162de146101c4578063715018a6146101da57600080fd5b80631d49c1ef1461010e578063238ac933146101375780632def66201461016f5780633644e5151461018657600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012460985481565b6040519081526020015b60405180910390f35b34801561014357600080fd5b50609a54610157906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b34801561017b57600080fd5b50610184610328565b005b34801561019257600080fd5b5061012460995481565b61018461043b565b3480156101b057600080fd5b50609c54610157906001600160a01b031681565b3480156101d057600080fd5b5061012460975481565b3480156101e657600080fd5b50610184610620565b3480156101fb57600080fd5b5061012461020a36600461189b565b610632565b34801561021b57600080fd5b5061018461022a3660046118f9565b6106ed565b34801561023b57600080fd5b506033546001600160a01b0316610157565b34801561025957600080fd5b5061018461026836600461189b565b61072a565b34801561027957600080fd5b50610184610288366004611935565b610bdf565b34801561029957600080fd5b506101246102a8366004611980565b609b60209081526000928352604080842090915290825290205481565b3480156102d157600080fd5b50610124609d5481565b3480156102e757600080fd5b506101846102f63660046119b3565b610e49565b34801561030757600080fd5b506101246103163660046119b3565b609e6020526000908152604090205481565b610330610ebf565b336000818152609e6020526040902054806103665760405162461bcd60e51b815260040161035d906119ce565b60405180910390fd5b6001600160a01b038281166000908152609e6020526040812055609c5416600019016103c8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103c2573d6000803e3d6000fd5b506103df565b609c546103df906001600160a01b03168383610f18565b609c54604080516001600160a01b038086168252909216602083015281018290527fcf268deaafc5a69317ec5abde2ac50c6e40212c584c1857c9868834999da957e9060600160405180910390a150506104396001606555565b565b610443610ebf565b609d54339061047f5760405162461bcd60e51b81526020600482015260086024820152676d696e5374616b6560c01b604482015260640161035d565b609d546001600160a01b0382166000908152609e6020526040902054106104b85760405162461bcd60e51b815260040161035d906119ce565b609d546001600160a01b0382166000908152609e60205260409020546104dd91610f87565b6001600160a01b038281166000908152609e6020526040902091909155609c54166000190161059457609d543410156105405760405162461bcd60e51b815260206004820152600560248201526476616c756560d81b604482015260640161035d565b609d5434111561058f57806001600160a01b03166108fc609d54346105659190611a04565b6040518115909202916000818181858888f1935050505015801561058d573d6000803e3d6000fd5b505b6105b3565b609d54609c546105b3916001600160a01b039091169083903090610f9c565b609c546001600160a01b038281166000818152609e60209081526040918290205482519384529390941693820193909352918201527f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f79060600160405180910390a1506104396001606555565b610628610fda565b6104396000611034565b609854600090819061064760208501856119b3565b602085013561066161065c6040880188611a17565b611086565b6040805160208101959095526001600160a01b03909316928401929092526060830152608082015260a001604051602081830303815290604052805190602001209050609954816040516020016106cf92919061190160f01b81526002810192909252602282015260420190565b60405160208183030381529060405280519060200120915050919050565b6106f5610fda565b609a80546001600160a01b039485166001600160a01b031991821617909155609c805493909416921691909117909155609d55565b610732610ebf565b61073b816111dc565b5060005b61074c6040830183611a17565b9050811015610bd15760006107646040840184611a17565b8381811061077457610774611a60565b61078a92602060609092020190810191506119b3565b6001600160a01b0316036107c85760405162461bcd60e51b81526020600482015260056024820152643a37b5b2b760d91b604482015260640161035d565b60006107d76040840184611a17565b838181106107e7576107e7611a60565b905060600201602001351161080e5760405162461bcd60e51b815260040161035d906119ce565b6000609b8161082060208601866119b3565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008480604001906108529190611a17565b8581811061086257610862611a60565b61087892602060609092020190810191506119b3565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050808380604001906108ac9190611a17565b848181106108bc576108bc611a60565b90506060020160400135146109005760405162461bcd60e51b815260206004820152600a6024820152691dda5d1a191c985dd95960b21b604482015260640161035d565b600061093b6109126040860186611a17565b8581811061092257610922611a60565b9050606002016020013583610f8790919063ffffffff16565b905080609b600061094f60208801886119b3565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008680604001906109819190611a17565b8781811061099157610991611a60565b6109a792602060609092020190810191506119b3565b6001600160a01b0316815260208101919091526040908101600020919091556001906109d590860186611a17565b858181106109e5576109e5611a60565b6109fb92602060609092020190810191506119b3565b6001600160a01b031603610a7a57610a1660208501856119b3565b6001600160a01b03166108fc610a2f6040870187611a17565b86818110610a3f57610a3f611a60565b905060600201602001359081150290604051600060405180830381858888f19350505050158015610a74573d6000803e3d6000fd5b50610af7565b610af7610a8a60208601866119b3565b610a976040870187611a17565b86818110610aa757610aa7611a60565b90506060020160200135868060400190610ac19190611a17565b87818110610ad157610ad1611a60565b610ae792602060609092020190810191506119b3565b6001600160a01b03169190610f18565b7f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645610b2560208601866119b3565b610b326040870187611a17565b86818110610b4257610b42611a60565b610b5892602060609092020190810191506119b3565b610b656040880188611a17565b87818110610b7557610b75611a60565b9050606002016020013584604051610bb494939291906001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60405180910390a150508080610bc990611a76565b91505061073f565b50610bdc6001606555565b50565b600054610100900460ff1615808015610bff5750600054600160ff909116105b80610c195750303b158015610c19575060005460ff166001145b610c7c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161035d565b6000805460ff191660011790558015610c9f576000805461ff0019166101001790555b610ca885611034565b610cb0611369565b609a80546001600160a01b038681166001600160a01b031992831617909255609c805492861692909116919091179055609d8290557f0fae6a861b837c5b0ad9a12416c45f5b90bb6eea66306907201000a6527a4dad6097557f4a69a0ad01584ab7752e8e795034577efc9deb56900e79bbcb25a50a80be7d7360985560408051808201825260088152674e66745374616b6560c01b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527fdb36fef4ebd2d971d1667fd52ebd65c995a5865b9fc7e0ea327696b5c36b7cff818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c090910190925281519101206099558015610e42576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610e51610fda565b6001600160a01b038116610eb65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161035d565b610bdc81611034565b600260655403610f115760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161035d565b6002606555565b6040516001600160a01b038316602482015260448101829052610f7b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611398565b505050565b6001606555565b6000610f938284611a8f565b90505b92915050565b6040516001600160a01b0380851660248301528316604482015260648101829052610fd49085906323b872dd60e01b90608401610f44565b50505050565b6033546001600160a01b031633146104395760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161035d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808267ffffffffffffffff8111156110a2576110a2611aa2565b6040519080825280602002602001820160405280156110cb578160200160208202803683370190505b5090508260005b818110156111aa576097548686838181106110ef576110ef611a60565b61110592602060609092020190810191506119b3565b87878481811061111757611117611a60565b9050606002016020013588888581811061113357611133611a60565b9050606002016040013560405160200161116f94939291909384526001600160a01b039290921660208401526040830152606082015260800190565b6040516020818303038152906040528051906020012083828151811061119757611197611a60565b60209081029190910101526001016110d2565b50816040516020016111bc9190611ab8565b604051602081830303815290604052805190602001209250505092915050565b6000336111ec60208401846119b3565b6001600160a01b03161461122b5760405162461bcd60e51b815260040161035d906020808252600490820152633ab9b2b960e11b604082015260600190565b428260200135101561126a5760405162461bcd60e51b8152602060048201526008602482015267646561646c696e6560c01b604482015260640161035d565b60006112796040840184611a17565b9050116112b05760405162461bcd60e51b8152602060048201526005602482015264185cdcd95d60da1b604482015260640161035d565b6112b982610632565b9050600061130a6112cd6060850185611aee565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869392505061146d9050565b90506001600160a01b038116158015906113315750609a546001600160a01b038281169116145b6113635760405162461bcd60e51b815260206004820152600360248201526273696760e81b604482015260640161035d565b50919050565b600054610100900460ff166113905760405162461bcd60e51b815260040161035d90611b35565b610439611491565b60006113ed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114b89092919063ffffffff16565b905080516000148061140e57508080602001905181019061140e9190611b80565b610f7b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161035d565b600080600061147c85856114cf565b9150915061148981611514565b509392505050565b600054610100900460ff16610f805760405162461bcd60e51b815260040161035d90611b35565b60606114c7848460008561165e565b949350505050565b60008082516041036115055760208301516040840151606085015160001a6114f987828585611739565b9450945050505061150d565b506000905060025b9250929050565b600081600481111561152857611528611ba2565b036115305750565b600181600481111561154457611544611ba2565b036115915760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161035d565b60028160048111156115a5576115a5611ba2565b036115f25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161035d565b600381600481111561160657611606611ba2565b03610bdc5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161035d565b6060824710156116bf5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161035d565b600080866001600160a01b031685876040516116db9190611bdc565b60006040518083038185875af1925050503d8060008114611718576040519150601f19603f3d011682016040523d82523d6000602084013e61171d565b606091505b509150915061172e878383876117fd565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561177057506000905060036117f4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156117c4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117ed576000600192509250506117f4565b9150600090505b94509492505050565b6060831561186c578251600003611865576001600160a01b0385163b6118655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161035d565b50816114c7565b6114c783838151156118815781518083602001fd5b8060405162461bcd60e51b815260040161035d9190611bf8565b6000602082840312156118ad57600080fd5b813567ffffffffffffffff8111156118c457600080fd5b8201608081850312156118d657600080fd5b9392505050565b80356001600160a01b03811681146118f457600080fd5b919050565b60008060006060848603121561190e57600080fd5b611917846118dd565b9250611925602085016118dd565b9150604084013590509250925092565b6000806000806080858703121561194b57600080fd5b611954856118dd565b9350611962602086016118dd565b9250611970604086016118dd565b9396929550929360600135925050565b6000806040838503121561199357600080fd5b61199c836118dd565b91506119aa602084016118dd565b90509250929050565b6000602082840312156119c557600080fd5b610f93826118dd565b602080825260069082015265185b5bdd5b9d60d21b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f9657610f966119ee565b6000808335601e19843603018112611a2e57600080fd5b83018035915067ffffffffffffffff821115611a4957600080fd5b602001915060608102360382131561150d57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060018201611a8857611a886119ee565b5060010190565b80820180821115610f9657610f966119ee565b634e487b7160e01b600052604160045260246000fd5b815160009082906020808601845b83811015611ae257815185529382019390820190600101611ac6565b50929695505050505050565b6000808335601e19843603018112611b0557600080fd5b83018035915067ffffffffffffffff821115611b2057600080fd5b60200191503681900382131561150d57600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215611b9257600080fd5b815180151581146118d657600080fd5b634e487b7160e01b600052602160045260246000fd5b60005b83811015611bd3578181015183820152602001611bbb565b50506000910152565b60008251611bee818460208701611bb8565b9190910192915050565b6020815260008251806020840152611c17816040850160208701611bb8565b601f01601f1916919091016040019291505056fea264697066735822122041efa89b6ae4caa9b63acb1e36a71e523ed1a04d6687b60e4da7e61aa589f21564736f6c63430008110033
Deployed Bytecode
0x6080604052600436106101025760003560e01c806374e2ce4411610095578063cf756fdf11610064578063cf756fdf1461026d578063e57c2c111461028d578063f1887684146102c5578063f2fde38b146102db578063f9931855146102fb57600080fd5b806374e2ce44146101ef5780638ce516da1461020f5780638da5cb5b1461022f578063be164af31461024d57600080fd5b80633a4b66f1116100d15780633a4b66f11461019c57806351ed6a30146101a4578063661162de146101c4578063715018a6146101da57600080fd5b80631d49c1ef1461010e578063238ac933146101375780632def66201461016f5780633644e5151461018657600080fd5b3661010957005b600080fd5b34801561011a57600080fd5b5061012460985481565b6040519081526020015b60405180910390f35b34801561014357600080fd5b50609a54610157906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b34801561017b57600080fd5b50610184610328565b005b34801561019257600080fd5b5061012460995481565b61018461043b565b3480156101b057600080fd5b50609c54610157906001600160a01b031681565b3480156101d057600080fd5b5061012460975481565b3480156101e657600080fd5b50610184610620565b3480156101fb57600080fd5b5061012461020a36600461189b565b610632565b34801561021b57600080fd5b5061018461022a3660046118f9565b6106ed565b34801561023b57600080fd5b506033546001600160a01b0316610157565b34801561025957600080fd5b5061018461026836600461189b565b61072a565b34801561027957600080fd5b50610184610288366004611935565b610bdf565b34801561029957600080fd5b506101246102a8366004611980565b609b60209081526000928352604080842090915290825290205481565b3480156102d157600080fd5b50610124609d5481565b3480156102e757600080fd5b506101846102f63660046119b3565b610e49565b34801561030757600080fd5b506101246103163660046119b3565b609e6020526000908152604090205481565b610330610ebf565b336000818152609e6020526040902054806103665760405162461bcd60e51b815260040161035d906119ce565b60405180910390fd5b6001600160a01b038281166000908152609e6020526040812055609c5416600019016103c8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103c2573d6000803e3d6000fd5b506103df565b609c546103df906001600160a01b03168383610f18565b609c54604080516001600160a01b038086168252909216602083015281018290527fcf268deaafc5a69317ec5abde2ac50c6e40212c584c1857c9868834999da957e9060600160405180910390a150506104396001606555565b565b610443610ebf565b609d54339061047f5760405162461bcd60e51b81526020600482015260086024820152676d696e5374616b6560c01b604482015260640161035d565b609d546001600160a01b0382166000908152609e6020526040902054106104b85760405162461bcd60e51b815260040161035d906119ce565b609d546001600160a01b0382166000908152609e60205260409020546104dd91610f87565b6001600160a01b038281166000908152609e6020526040902091909155609c54166000190161059457609d543410156105405760405162461bcd60e51b815260206004820152600560248201526476616c756560d81b604482015260640161035d565b609d5434111561058f57806001600160a01b03166108fc609d54346105659190611a04565b6040518115909202916000818181858888f1935050505015801561058d573d6000803e3d6000fd5b505b6105b3565b609d54609c546105b3916001600160a01b039091169083903090610f9c565b609c546001600160a01b038281166000818152609e60209081526040918290205482519384529390941693820193909352918201527f99039fcf0a98f484616c5196ee8b2ecfa971babf0b519848289ea4db381f85f79060600160405180910390a1506104396001606555565b610628610fda565b6104396000611034565b609854600090819061064760208501856119b3565b602085013561066161065c6040880188611a17565b611086565b6040805160208101959095526001600160a01b03909316928401929092526060830152608082015260a001604051602081830303815290604052805190602001209050609954816040516020016106cf92919061190160f01b81526002810192909252602282015260420190565b60405160208183030381529060405280519060200120915050919050565b6106f5610fda565b609a80546001600160a01b039485166001600160a01b031991821617909155609c805493909416921691909117909155609d55565b610732610ebf565b61073b816111dc565b5060005b61074c6040830183611a17565b9050811015610bd15760006107646040840184611a17565b8381811061077457610774611a60565b61078a92602060609092020190810191506119b3565b6001600160a01b0316036107c85760405162461bcd60e51b81526020600482015260056024820152643a37b5b2b760d91b604482015260640161035d565b60006107d76040840184611a17565b838181106107e7576107e7611a60565b905060600201602001351161080e5760405162461bcd60e51b815260040161035d906119ce565b6000609b8161082060208601866119b3565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008480604001906108529190611a17565b8581811061086257610862611a60565b61087892602060609092020190810191506119b3565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050808380604001906108ac9190611a17565b848181106108bc576108bc611a60565b90506060020160400135146109005760405162461bcd60e51b815260206004820152600a6024820152691dda5d1a191c985dd95960b21b604482015260640161035d565b600061093b6109126040860186611a17565b8581811061092257610922611a60565b9050606002016020013583610f8790919063ffffffff16565b905080609b600061094f60208801886119b3565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008680604001906109819190611a17565b8781811061099157610991611a60565b6109a792602060609092020190810191506119b3565b6001600160a01b0316815260208101919091526040908101600020919091556001906109d590860186611a17565b858181106109e5576109e5611a60565b6109fb92602060609092020190810191506119b3565b6001600160a01b031603610a7a57610a1660208501856119b3565b6001600160a01b03166108fc610a2f6040870187611a17565b86818110610a3f57610a3f611a60565b905060600201602001359081150290604051600060405180830381858888f19350505050158015610a74573d6000803e3d6000fd5b50610af7565b610af7610a8a60208601866119b3565b610a976040870187611a17565b86818110610aa757610aa7611a60565b90506060020160200135868060400190610ac19190611a17565b87818110610ad157610ad1611a60565b610ae792602060609092020190810191506119b3565b6001600160a01b03169190610f18565b7f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645610b2560208601866119b3565b610b326040870187611a17565b86818110610b4257610b42611a60565b610b5892602060609092020190810191506119b3565b610b656040880188611a17565b87818110610b7557610b75611a60565b9050606002016020013584604051610bb494939291906001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60405180910390a150508080610bc990611a76565b91505061073f565b50610bdc6001606555565b50565b600054610100900460ff1615808015610bff5750600054600160ff909116105b80610c195750303b158015610c19575060005460ff166001145b610c7c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161035d565b6000805460ff191660011790558015610c9f576000805461ff0019166101001790555b610ca885611034565b610cb0611369565b609a80546001600160a01b038681166001600160a01b031992831617909255609c805492861692909116919091179055609d8290557f0fae6a861b837c5b0ad9a12416c45f5b90bb6eea66306907201000a6527a4dad6097557f4a69a0ad01584ab7752e8e795034577efc9deb56900e79bbcb25a50a80be7d7360985560408051808201825260088152674e66745374616b6560c01b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527fdb36fef4ebd2d971d1667fd52ebd65c995a5865b9fc7e0ea327696b5c36b7cff818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c090910190925281519101206099558015610e42576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610e51610fda565b6001600160a01b038116610eb65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161035d565b610bdc81611034565b600260655403610f115760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161035d565b6002606555565b6040516001600160a01b038316602482015260448101829052610f7b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611398565b505050565b6001606555565b6000610f938284611a8f565b90505b92915050565b6040516001600160a01b0380851660248301528316604482015260648101829052610fd49085906323b872dd60e01b90608401610f44565b50505050565b6033546001600160a01b031633146104395760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161035d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808267ffffffffffffffff8111156110a2576110a2611aa2565b6040519080825280602002602001820160405280156110cb578160200160208202803683370190505b5090508260005b818110156111aa576097548686838181106110ef576110ef611a60565b61110592602060609092020190810191506119b3565b87878481811061111757611117611a60565b9050606002016020013588888581811061113357611133611a60565b9050606002016040013560405160200161116f94939291909384526001600160a01b039290921660208401526040830152606082015260800190565b6040516020818303038152906040528051906020012083828151811061119757611197611a60565b60209081029190910101526001016110d2565b50816040516020016111bc9190611ab8565b604051602081830303815290604052805190602001209250505092915050565b6000336111ec60208401846119b3565b6001600160a01b03161461122b5760405162461bcd60e51b815260040161035d906020808252600490820152633ab9b2b960e11b604082015260600190565b428260200135101561126a5760405162461bcd60e51b8152602060048201526008602482015267646561646c696e6560c01b604482015260640161035d565b60006112796040840184611a17565b9050116112b05760405162461bcd60e51b8152602060048201526005602482015264185cdcd95d60da1b604482015260640161035d565b6112b982610632565b9050600061130a6112cd6060850185611aee565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869392505061146d9050565b90506001600160a01b038116158015906113315750609a546001600160a01b038281169116145b6113635760405162461bcd60e51b815260206004820152600360248201526273696760e81b604482015260640161035d565b50919050565b600054610100900460ff166113905760405162461bcd60e51b815260040161035d90611b35565b610439611491565b60006113ed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114b89092919063ffffffff16565b905080516000148061140e57508080602001905181019061140e9190611b80565b610f7b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161035d565b600080600061147c85856114cf565b9150915061148981611514565b509392505050565b600054610100900460ff16610f805760405162461bcd60e51b815260040161035d90611b35565b60606114c7848460008561165e565b949350505050565b60008082516041036115055760208301516040840151606085015160001a6114f987828585611739565b9450945050505061150d565b506000905060025b9250929050565b600081600481111561152857611528611ba2565b036115305750565b600181600481111561154457611544611ba2565b036115915760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161035d565b60028160048111156115a5576115a5611ba2565b036115f25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161035d565b600381600481111561160657611606611ba2565b03610bdc5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161035d565b6060824710156116bf5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161035d565b600080866001600160a01b031685876040516116db9190611bdc565b60006040518083038185875af1925050503d8060008114611718576040519150601f19603f3d011682016040523d82523d6000602084013e61171d565b606091505b509150915061172e878383876117fd565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561177057506000905060036117f4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156117c4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117ed576000600192509250506117f4565b9150600090505b94509492505050565b6060831561186c578251600003611865576001600160a01b0385163b6118655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161035d565b50816114c7565b6114c783838151156118815781518083602001fd5b8060405162461bcd60e51b815260040161035d9190611bf8565b6000602082840312156118ad57600080fd5b813567ffffffffffffffff8111156118c457600080fd5b8201608081850312156118d657600080fd5b9392505050565b80356001600160a01b03811681146118f457600080fd5b919050565b60008060006060848603121561190e57600080fd5b611917846118dd565b9250611925602085016118dd565b9150604084013590509250925092565b6000806000806080858703121561194b57600080fd5b611954856118dd565b9350611962602086016118dd565b9250611970604086016118dd565b9396929550929360600135925050565b6000806040838503121561199357600080fd5b61199c836118dd565b91506119aa602084016118dd565b90509250929050565b6000602082840312156119c557600080fd5b610f93826118dd565b602080825260069082015265185b5bdd5b9d60d21b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f9657610f966119ee565b6000808335601e19843603018112611a2e57600080fd5b83018035915067ffffffffffffffff821115611a4957600080fd5b602001915060608102360382131561150d57600080fd5b634e487b7160e01b600052603260045260246000fd5b600060018201611a8857611a886119ee565b5060010190565b80820180821115610f9657610f966119ee565b634e487b7160e01b600052604160045260246000fd5b815160009082906020808601845b83811015611ae257815185529382019390820190600101611ac6565b50929695505050505050565b6000808335601e19843603018112611b0557600080fd5b83018035915067ffffffffffffffff821115611b2057600080fd5b60200191503681900382131561150d57600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215611b9257600080fd5b815180151581146118d657600080fd5b634e487b7160e01b600052602160045260246000fd5b60005b83811015611bd3578181015183820152602001611bbb565b50506000910152565b60008251611bee818460208701611bb8565b9190910192915050565b6020815260008251806020840152611c17816040850160208701611bb8565b601f01601f1916919091016040019291505056fea264697066735822122041efa89b6ae4caa9b63acb1e36a71e523ed1a04d6687b60e4da7e61aa589f21564736f6c63430008110033
Deployed Bytecode Sourcemap
318:7130:7:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;695:25;;;;;;;;;;;;;;;;;;;160::14;;;148:2;133:18;695:25:7;;;;;;;;820:21;;;;;;;;;;-1:-1:-1;820:21:7;;;;-1:-1:-1;;;;;820:21:7;;;;;;-1:-1:-1;;;;;360:32:14;;;342:51;;330:2;315:18;820:21:7;196:203:14;4294:445:7;;;;;;;;;;;;;:::i;:::-;;750:31;;;;;;;;;;;;;;;;3621:667;;;:::i;1583:25::-;;;;;;;;;;-1:-1:-1;1583:25:7;;;;-1:-1:-1;;;;;1583:25:7;;;605;;;;;;;;;;;;;;;;2065:101:8;;;;;;;;;;;;;:::i;6550:356:7:-;;;;;;;;;;-1:-1:-1;6550:356:7;;;;;:::i;:::-;;:::i;3409:206::-;;;;;;;;;;-1:-1:-1;3409:206:7;;;;;:::i;:::-;;:::i;1442:85:8:-;;;;;;;;;;-1:-1:-1;1514:6:8;;-1:-1:-1;;;;;1514:6:8;1442:85;;4871:918:7;;;;;;;;;;-1:-1:-1;4871:918:7;;;;;:::i;:::-;;:::i;2236:956::-;;;;;;;;;;-1:-1:-1;2236:956:7;;;;;:::i;:::-;;:::i;1484:71::-;;;;;;;;;;-1:-1:-1;1484:71:7;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1643:29;;;;;;;;;;;;;;;;2315:198:8;;;;;;;;;;-1:-1:-1;2315:198:8;;;;;:::i;:::-;;:::i;1717:47:7:-;;;;;;;;;;-1:-1:-1;1717:47:7;;;;;:::i;:::-;;;;;;;;;;;;;;4294:445;2513:21:9;:19;:21::i;:::-;4358:10:7::1;4343:12;4400:18:::0;;;:12:::1;:18;::::0;;;;;4436:15;4428:33:::1;;;;-1:-1:-1::0;;;4428:33:7::1;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1::0;;;;;4471:18:7;;::::1;4492:1;4471:18:::0;;;:12:::1;:18;::::0;;;;:22;4506:10:::1;::::0;::::1;-1:-1:-1::0;;4506:24:7;4503:177:::1;;4545:35;::::0;-1:-1:-1;;;;;4545:22:7;::::1;::::0;:35;::::1;;;::::0;4568:11;;4545:35:::1;::::0;;;4568:11;4545:22;:35;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;4503:177;;;4627:10;::::0;4609:60:::1;::::0;-1:-1:-1;;;;;4627:10:7::1;4652:4:::0;4657:11;4609:42:::1;:60::i;:::-;4708:10;::::0;4694:38:::1;::::0;;-1:-1:-1;;;;;2943:15:14;;;2925:34;;4708:10:7;;::::1;2990:2:14::0;2975:18;;2968:43;3027:18;;3020:34;;;4694:38:7::1;::::0;2875:2:14;2860:18;4694:38:7::1;;;;;;;4333:406;;2555:20:9::0;1795:1;3061:7;:22;2881:209;2555:20;4294:445:7:o;3621:667::-;2513:21:9;:19;:21::i;:::-;3719:14:7::1;::::0;3691:10:::1;::::0;3711:38:::1;;;::::0;-1:-1:-1;;;3711:38:7;;3267:2:14;3711:38:7::1;::::0;::::1;3249:21:14::0;3306:1;3286:18;;;3279:29;-1:-1:-1;;;3324:18:14;;;3317:38;3372:18;;3711:38:7::1;3065:331:14::0;3711:38:7::1;3788:14;::::0;-1:-1:-1;;;;;3767:18:7;::::1;;::::0;;;:12:::1;:18;::::0;;;;;:35:::1;3759:53;;;;-1:-1:-1::0;;;3759:53:7::1;;;;;;;:::i;:::-;3866:14;::::0;-1:-1:-1;;;;;3843:18:7;::::1;;::::0;;;:12:::1;:18;::::0;;;;;:38:::1;::::0;:22:::1;:38::i;:::-;-1:-1:-1::0;;;;;3822:18:7;;::::1;;::::0;;;:12:::1;:18;::::0;;;;:59;;;;3894:10:::1;::::0;::::1;-1:-1:-1::0;;3894:24:7;3891:333:::1;;3954:14;;3941:9;:27;;3933:44;;;::::0;-1:-1:-1;;;3933:44:7;;3603:2:14;3933:44:7::1;::::0;::::1;3585:21:14::0;3642:1;3622:18;;;3615:29;-1:-1:-1;;;3660:18:14;;;3653:35;3705:18;;3933:44:7::1;3401:328:14::0;3933:44:7::1;4006:14;;3994:9;:26;3991:113;;;4047:4;-1:-1:-1::0;;;;;4039:22:7::1;:50;4074:14;;4062:9;:26;;;;:::i;:::-;4039:50;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;3991:113;3891:333;;;4198:14;::::0;4150:10:::1;::::0;4132:81:::1;::::0;-1:-1:-1;;;;;4150:10:7;;::::1;::::0;4179:4;;4192::::1;::::0;4132:46:::1;:81::i;:::-;4250:10;::::0;-1:-1:-1;;;;;4262:18:7;;::::1;4250:10;4262:18:::0;;;:12:::1;:18;::::0;;;;;;;;;4238:43;;2925:34:14;;;4250:10:7;;;::::1;2975:18:14::0;;;2968:43;;;;3027:18;;;3020:34;4238:43:7::1;::::0;2875:2:14;2860:18;4238:43:7::1;;;;;;;3666:622;2555:20:9::0;1795:1;3061:7;:22;2881:209;2065:101:8;1335:13;:11;:13::i;:::-;2129:30:::1;2156:1;2129:18;:30::i;6550:356:7:-:0;6696:10;;6612:17;;;;6720:10;;;;:5;:10;:::i;:::-;6744:14;;;;6772:23;6783:11;;;;6744:5;6783:11;:::i;:::-;6772:10;:23::i;:::-;6672:133;;;;;;4808:25:14;;;;-1:-1:-1;;;;;4869:32:14;;;4849:18;;;4842:60;;;;4918:18;;;4911:34;4961:18;;;4954:34;4780:19;;6672:133:7;;;;;;;;;;;;6662:144;;;;;;6641:165;;6868:16;;6886:10;6839:58;;;;;;;;-1:-1:-1;;;5257:27:14;;5309:1;5300:11;;5293:27;;;;5345:2;5336:12;;5329:28;5382:2;5373:12;;4999:392;6839:58:7;;;;;;;;;;;;;6828:71;;;;;;6816:83;;6631:275;6550:356;;;:::o;3409:206::-;1335:13:8;:11;:13::i;:::-;3515:6:7::1;:17:::0;;-1:-1:-1;;;;;3515:17:7;;::::1;-1:-1:-1::0;;;;;;3515:17:7;;::::1;;::::0;;;3542:10:::1;:24:::0;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;3576:14:::1;:32:::0;3409:206::o;4871:918::-;2513:21:9;:19;:21::i;:::-;4939:17:7::1;4949:6;4939:9;:17::i;:::-;;4970:6;4966:817;4981:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;:19;;4979:1;:21;4966:817;;;5060:1;5027:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5040:1;5027:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5027:21:7::1;:::i;:::-;-1:-1:-1::0;;;;;5027:35:7::1;::::0;5019:52:::1;;;::::0;-1:-1:-1;;;5019:52:7;;5730:2:14;5019:52:7::1;::::0;::::1;5712:21:14::0;5769:1;5749:18;;;5742:29;-1:-1:-1;;;5787:18:14;;;5780:35;5832:18;;5019:52:7::1;5528:328:14::0;5019:52:7::1;5118:1;5093:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5106:1;5093:15;;;;;;;:::i;:::-;;;;;;:22;;;:26;5085:44;;;;-1:-1:-1::0;;;5085:44:7::1;;;;;;;:::i;:::-;5143:12;5158:16;5143:12:::0;5175:11:::1;;::::0;::::1;:6:::0;:11:::1;:::i;:::-;-1:-1:-1::0;;;;;5158:29:7::1;-1:-1:-1::0;;;;;5158:29:7::1;;;;;;;;;;;;:52;5188:6;:12;;;;;;;;:::i;:::-;5201:1;5188:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5188:21:7::1;:::i;:::-;-1:-1:-1::0;;;;;5158:52:7::1;-1:-1:-1::0;;;;;5158:52:7::1;;;;;;;;;;;;;5143:67;;5262:4;5232:6;:12;;;;;;;;:::i;:::-;5245:1;5232:15;;;;;;;:::i;:::-;;;;;;:26;;;:34;5224:57;;;::::0;-1:-1:-1;;;5224:57:7;;6063:2:14;5224:57:7::1;::::0;::::1;6045:21:14::0;6102:2;6082:18;;;6075:30;-1:-1:-1;;;6121:18:14;;;6114:40;6171:18;;5224:57:7::1;5861:334:14::0;5224:57:7::1;5295:13;5311:32;5320:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5333:1;5320:15;;;;;;;:::i;:::-;;;;;;:22;;;5311:4;:8;;:32;;;;:::i;:::-;5295:48:::0;-1:-1:-1;5295:48:7;5357:16:::1;:29;5374:11;;::::0;::::1;:6:::0;:11:::1;:::i;:::-;-1:-1:-1::0;;;;;5357:29:7::1;-1:-1:-1::0;;;;;5357:29:7::1;;;;;;;;;;;;:52;5387:6;:12;;;;;;;;:::i;:::-;5400:1;5387:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5387:21:7::1;:::i;:::-;-1:-1:-1::0;;;;;5357:52:7::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;-1:-1:-1;5357:52:7;:60;;;;5467:1:::1;::::0;5434:12:::1;::::0;;::::1;:6:::0;:12:::1;:::i;:::-;5447:1;5434:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5434:21:7::1;:::i;:::-;-1:-1:-1::0;;;;;5434:35:7::1;::::0;5431:251:::1;;5496:11;;::::0;::::1;:6:::0;:11:::1;:::i;:::-;-1:-1:-1::0;;;;;5488:29:7::1;:53;5518:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5531:1;5518:15;;;;;;;:::i;:::-;;;;;;:22;;;5488:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;5431:251;;;5578:89;5632:11;;::::0;::::1;:6:::0;:11:::1;:::i;:::-;5644:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5657:1;5644:15;;;;;;;:::i;:::-;;;;;;:22;;;5596:6;:12;;;;;;;;:::i;:::-;5609:1;5596:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5596:21:7::1;:::i;:::-;-1:-1:-1::0;;;;;5578:53:7::1;::::0;:89;:53:::1;:89::i;:::-;5700:72;5706:11;;::::0;::::1;:6:::0;:11:::1;:::i;:::-;5719:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5732:1;5719:15;;;;;;;:::i;:::-;:21;::::0;::::1;:15;::::0;;::::1;;:21:::0;;::::1;::::0;-1:-1:-1;5719:21:7::1;:::i;:::-;5742:12;;::::0;::::1;:6:::0;:12:::1;:::i;:::-;5755:1;5742:15;;;;;;;:::i;:::-;;;;;;:22;;;5766:5;5700:72;;;;;;;;-1:-1:-1::0;;;;;6487:15:14;;;6469:34;;6539:15;;;;6534:2;6519:18;;6512:43;6586:2;6571:18;;6564:34;6629:2;6614:18;;6607:34;;;;6418:3;6403:19;;6200:447;5700:72:7::1;;;;;;;;5005:778;;5001:3;;;;;:::i;:::-;;;;4966:817;;;;2555:20:9::0;1795:1;3061:7;:22;2881:209;2555:20;4871:918:7;:::o;2236:956::-;3269:19:5;3292:13;;;;;;3291:14;;3337:34;;;;-1:-1:-1;3355:12:5;;3370:1;3355:12;;;;:16;3337:34;3336:108;;;-1:-1:-1;3416:4:5;1713:19:0;:23;;;3377:66:5;;-1:-1:-1;3426:12:5;;;;;:17;3377:66;3315:201;;;;-1:-1:-1;;;3315:201:5;;6994:2:14;3315:201:5;;;6976:21:14;7033:2;7013:18;;;7006:30;7072:34;7052:18;;;7045:62;-1:-1:-1;;;7123:18:14;;;7116:44;7177:19;;3315:201:5;6792:410:14;3315:201:5;3526:12;:16;;-1:-1:-1;;3526:16:5;3541:1;3526:16;;;3552:65;;;;3586:13;:20;;-1:-1:-1;;3586:20:5;;;;;3552:65;2363:26:7::1;2382:6;2363:18;:26::i;:::-;2399:24;:22;:24::i;:::-;2433:6;:16:::0;;-1:-1:-1;;;;;2433:16:7;;::::1;-1:-1:-1::0;;;;;;2433:16:7;;::::1;;::::0;;;2459:10:::1;:24:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;2493:14:::1;:32:::0;;;2548:67:::1;2535:10;:80:::0;2639:117:::1;2626:10;:130:::0;3048:17:::1;::::0;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;;3048:17:7::1;::::0;;::::1;::::0;3094:10;;;;::::1;::::0;;-1:-1:-1;3094:10:7;;-1:-1:-1;;;3094:10:7;;::::1;::::0;2897:278;;2925:95:::1;2897:278:::0;;::::1;7466:25:14::0;3038:28:7;7507:18:14;;;7500:34;3084:21:7;7550:18:14;;;7543:34;2826:9:7::1;7593:18:14::0;;;7586:34;3156:4:7::1;7636:19:14::0;;;;7629:61;;;;2897:278:7;;;;;;;;;;7438:19:14;;;;2897:278:7;;;2874:311;;;::::1;::::0;2855:16:::1;:330:::0;3637:99:5;;;;3687:5;3671:21;;-1:-1:-1;;3671:21:5;;;3711:14;;-1:-1:-1;7853:36:14;;3711:14:5;;7841:2:14;7826:18;3711:14:5;;;;;;;3637:99;3259:483;2236:956:7;;;;:::o;2315:198:8:-;1335:13;:11;:13::i;:::-;-1:-1:-1;;;;;2403:22:8;::::1;2395:73;;;::::0;-1:-1:-1;;;2395:73:8;;8102:2:14;2395:73:8::1;::::0;::::1;8084:21:14::0;8141:2;8121:18;;;8114:30;8180:34;8160:18;;;8153:62;-1:-1:-1;;;8231:18:14;;;8224:36;8277:19;;2395:73:8::1;7900:402:14::0;2395:73:8::1;2478:28;2497:8;2478:18;:28::i;2588:287:9:-:0;1838:1;2720:7;;:19;2712:63;;;;-1:-1:-1;;;2712:63:9;;8509:2:14;2712:63:9;;;8491:21:14;8548:2;8528:18;;;8521:30;8587:33;8567:18;;;8560:61;8638:18;;2712:63:9;8307:355:14;2712:63:9;1838:1;2850:7;:18;2588:287::o;970:186:10:-;1090:58;;-1:-1:-1;;;;;8859:32:14;;1090:58:10;;;8841:51:14;8908:18;;;8901:34;;;1063:86:10;;1083:5;;-1:-1:-1;;;1113:23:10;8814:18:14;;1090:58:10;;;;-1:-1:-1;;1090:58:10;;;;;;;;;;;;;;-1:-1:-1;;;;;1090:58:10;-1:-1:-1;;;;;;1090:58:10;;;;;;;;;;1063:19;:86::i;:::-;970:186;;;:::o;2881:209:9:-;1795:1;3061:7;:22;2881:209::o;2766:96:11:-;2824:7;2850:5;2854:1;2850;:5;:::i;:::-;2843:12;;2766:96;;;;;:::o;1395:214:10:-;1533:68;;-1:-1:-1;;;;;2943:15:14;;;1533:68:10;;;2925:34:14;2995:15;;2975:18;;;2968:43;3027:18;;;3020:34;;;1506:96:10;;1526:5;;-1:-1:-1;;;1556:27:10;2860:18:14;;1533:68:10;2685:375:14;1506:96:10;1395:214;;;;:::o;1600:130:8:-;1514:6;;-1:-1:-1;;;;;1514:6:8;952:10:1;1663:23:8;1655:68;;;;-1:-1:-1;;;1655:68:8;;9278:2:14;1655:68:8;;;9260:21:14;;;9297:18;;;9290:30;9356:34;9336:18;;;9329:62;9408:18;;1655:68:8;9076:356:14;2667:187:8;2759:6;;;-1:-1:-1;;;;;2775:17:8;;;-1:-1:-1;;;;;;2775:17:8;;;;;;;2807:40;;2759:6;;;2775:17;2759:6;;2807:40;;2740:16;;2807:40;2730:124;2667:187;:::o;5925:491:7:-;5993:7;;6057:6;6043:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6043:28:7;-1:-1:-1;6012:59:7;-1:-1:-1;6104:6:7;6081:20;6127:226;6147:12;6143:1;:16;6127:226;;;6215:10;;6227:6;;6234:1;6227:9;;;;;;;:::i;:::-;:15;;;:9;;;;;:15;;;;-1:-1:-1;6227:15:7;:::i;:::-;6244:6;;6251:1;6244:9;;;;;;;:::i;:::-;;;;;;:16;;;6261:6;;6268:1;6261:9;;;;;;;:::i;:::-;;;;;;:20;;;6204:78;;;;;;;;;;4808:25:14;;;-1:-1:-1;;;;;4869:32:14;;;;4864:2;4849:18;;4842:60;4933:2;4918:18;;4911:34;4976:2;4961:18;;4954:34;4795:3;4780:19;;4577:417;6204:78:7;;;;;;;;;;;;;6194:89;;;;;;6177:11;6189:1;6177:14;;;;;;;;:::i;:::-;;;;;;;;;;:106;6325:3;;6127:226;;;;6396:11;6379:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;6369:40;;;;;;6362:47;;;;5925:491;;;;:::o;7033:413::-;7097:14;7145:10;7131;;;;:5;:10;:::i;:::-;-1:-1:-1;;;;;7131:24:7;;7123:40;;;;-1:-1:-1;;;7123:40:7;;;;;;10741:2:14;10723:21;;;10780:1;10760:18;;;10753:29;-1:-1:-1;;;10813:2:14;10798:18;;10791:34;10857:2;10842:18;;10539:327;7123:40:7;7199:15;7181:5;:14;;;:33;;7173:54;;;;-1:-1:-1;;;7173:54:7;;11073:2:14;7173:54:7;;;11055:21:14;11112:1;11092:18;;;11085:29;-1:-1:-1;;;11130:18:14;;;11123:38;11178:18;;7173:54:7;10871:331:14;7173:54:7;7266:1;7245:11;;;;:5;:11;:::i;:::-;:18;;:22;7237:40;;;;-1:-1:-1;;;7237:40:7;;11409:2:14;7237:40:7;;;11391:21:14;11448:1;11428:18;;;11421:29;-1:-1:-1;;;11466:18:14;;;11459:35;11511:18;;7237:40:7;11207:328:14;7237:40:7;7296:16;7306:5;7296:9;:16::i;:::-;7287:25;-1:-1:-1;7322:17:7;7342:25;7357:9;;;;:5;:9;:::i;:::-;7342:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7342:6:7;;:25;-1:-1:-1;;7342:14:7;:25;-1:-1:-1;7342:25:7:i;:::-;7322:45;-1:-1:-1;;;;;;7385:23:7;;;;;;:46;;-1:-1:-1;7412:6:7;;-1:-1:-1;;;;;7412:19:7;;;:6;;:19;7385:46;7377:62;;;;-1:-1:-1;;;7377:62:7;;12268:2:14;7377:62:7;;;12250:21:14;12307:1;12287:18;;;12280:29;-1:-1:-1;;;12325:18:14;;;12318:33;12368:18;;7377:62:7;12066:326:14;7377:62:7;7113:333;7033:413;;;:::o;1876:111:9:-;5364:13:5;;;;;;;5356:69;;;;-1:-1:-1;;;5356:69:5;;;;;;;:::i;:::-;1946:34:9::1;:32;:34::i;5302:653:10:-:0;5732:23;5758:69;5786:4;5758:69;;;;;;;;;;;;;;;;;5766:5;-1:-1:-1;;;;;5758:27:10;;;:69;;;;;:::i;:::-;5732:95;;5845:10;:17;5866:1;5845:22;:56;;;;5882:10;5871:30;;;;;;;;;;;;:::i;:::-;5837:111;;;;-1:-1:-1;;;5837:111:10;;13293:2:14;5837:111:10;;;13275:21:14;13332:2;13312:18;;;13305:30;13371:34;13351:18;;;13344:62;-1:-1:-1;;;13422:18:14;;;13415:40;13472:19;;5837:111:10;13091:406:14;3682:227:2;3760:7;3780:17;3799:18;3821:27;3832:4;3838:9;3821:10;:27::i;:::-;3779:69;;;;3858:18;3870:5;3858:11;:18::i;:::-;-1:-1:-1;3893:9:2;3682:227;-1:-1:-1;;;3682:227:2:o;1993:109:9:-;5364:13:5;;;;;;;5356:69;;;;-1:-1:-1;;;5356:69:5;;;;;;;:::i;4119:223:0:-;4252:12;4283:52;4305:6;4313:4;4319:1;4322:12;4283:21;:52::i;:::-;4276:59;4119:223;-1:-1:-1;;;;4119:223:0:o;2166:730:2:-;2247:7;2256:12;2284:9;:16;2304:2;2284:22;2280:610;;2620:4;2605:20;;2599:27;2669:4;2654:20;;2648:27;2726:4;2711:20;;2705:27;2322:9;2697:36;2767:25;2778:4;2697:36;2599:27;2648;2767:10;:25::i;:::-;2760:32;;;;;;;;;2280:610;-1:-1:-1;2839:1:2;;-1:-1:-1;2843:35:2;2280:610;2166:730;;;;;:::o;591:511::-;668:20;659:5;:29;;;;;;;;:::i;:::-;;655:441;;591:511;:::o;655:441::-;764:29;755:5;:38;;;;;;;;:::i;:::-;;751:345;;809:34;;-1:-1:-1;;;809:34:2;;13836:2:14;809:34:2;;;13818:21:14;13875:2;13855:18;;;13848:30;13914:26;13894:18;;;13887:54;13958:18;;809:34:2;13634:348:14;751:345:2;873:35;864:5;:44;;;;;;;;:::i;:::-;;860:236;;924:41;;-1:-1:-1;;;924:41:2;;14189:2:14;924:41:2;;;14171:21:14;14228:2;14208:18;;;14201:30;14267:33;14247:18;;;14240:61;14318:18;;924:41:2;13987:355:14;860:236:2;995:30;986:5;:39;;;;;;;;:::i;:::-;;982:114;;1041:44;;-1:-1:-1;;;1041:44:2;;14549:2:14;1041:44:2;;;14531:21:14;14588:2;14568:18;;;14561:30;14627:34;14607:18;;;14600:62;-1:-1:-1;;;14678:18:14;;;14671:32;14720:19;;1041:44:2;14347:398:14;5176:446:0;5341:12;5398:5;5373:21;:30;;5365:81;;;;-1:-1:-1;;;5365:81:0;;14952:2:14;5365:81:0;;;14934:21:14;14991:2;14971:18;;;14964:30;15030:34;15010:18;;;15003:62;-1:-1:-1;;;15081:18:14;;;15074:36;15127:19;;5365:81:0;14750:402:14;5365:81:0;5457:12;5471:23;5498:6;-1:-1:-1;;;;;5498:11:0;5517:5;5524:4;5498:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5456:73;;;;5546:69;5573:6;5581:7;5590:10;5602:12;5546:26;:69::i;:::-;5539:76;5176:446;-1:-1:-1;;;;;;;5176:446:0:o;5030:1456:2:-;5118:7;;6042:66;6029:79;;6025:161;;;-1:-1:-1;6140:1:2;;-1:-1:-1;6144:30:2;6124:51;;6025:161;6297:24;;;6280:14;6297:24;;;;;;;;;15931:25:14;;;16004:4;15992:17;;15972:18;;;15965:45;;;;16026:18;;;16019:34;;;16069:18;;;16062:34;;;6297:24:2;;15903:19:14;;6297:24:2;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6297:24:2;;-1:-1:-1;;6297:24:2;;;-1:-1:-1;;;;;;;6335:20:2;;6331:101;;6387:1;6391:29;6371:50;;;;;;;6331:101;6450:6;-1:-1:-1;6458:20:2;;-1:-1:-1;5030:1456:2;;;;;;;;:::o;7682:628:0:-;7862:12;7890:7;7886:418;;;7917:10;:17;7938:1;7917:22;7913:286;;-1:-1:-1;;;;;1713:19:0;;;8124:60;;;;-1:-1:-1;;;8124:60:0;;16309:2:14;8124:60:0;;;16291:21:14;16348:2;16328:18;;;16321:30;16387:31;16367:18;;;16360:59;16436:18;;8124:60:0;16107:353:14;8124:60:0;-1:-1:-1;8219:10:0;8212:17;;7886:418;8260:33;8268:10;8280:12;8991:17;;:21;8987:379;;9219:10;9213:17;9275:15;9262:10;9258:2;9254:19;9247:44;8987:379;9342:12;9335:20;;-1:-1:-1;;;9335:20:0;;;;;;;;:::i;404:385:14:-;488:6;541:2;529:9;520:7;516:23;512:32;509:52;;;557:1;554;547:12;509:52;597:9;584:23;630:18;622:6;619:30;616:50;;;662:1;659;652:12;616:50;685:22;;741:3;723:16;;;719:26;716:46;;;758:1;755;748:12;716:46;781:2;404:385;-1:-1:-1;;;404:385:14:o;794:173::-;862:20;;-1:-1:-1;;;;;911:31:14;;901:42;;891:70;;957:1;954;947:12;891:70;794:173;;;:::o;972:328::-;1049:6;1057;1065;1118:2;1106:9;1097:7;1093:23;1089:32;1086:52;;;1134:1;1131;1124:12;1086:52;1157:29;1176:9;1157:29;:::i;:::-;1147:39;;1205:38;1239:2;1228:9;1224:18;1205:38;:::i;:::-;1195:48;;1290:2;1279:9;1275:18;1262:32;1252:42;;972:328;;;;;:::o;1305:403::-;1391:6;1399;1407;1415;1468:3;1456:9;1447:7;1443:23;1439:33;1436:53;;;1485:1;1482;1475:12;1436:53;1508:29;1527:9;1508:29;:::i;:::-;1498:39;;1556:38;1590:2;1579:9;1575:18;1556:38;:::i;:::-;1546:48;;1613:38;1647:2;1636:9;1632:18;1613:38;:::i;:::-;1305:403;;;;-1:-1:-1;1603:48:14;;1698:2;1683:18;1670:32;;-1:-1:-1;;1305:403:14:o;1713:260::-;1781:6;1789;1842:2;1830:9;1821:7;1817:23;1813:32;1810:52;;;1858:1;1855;1848:12;1810:52;1881:29;1900:9;1881:29;:::i;:::-;1871:39;;1929:38;1963:2;1952:9;1948:18;1929:38;:::i;:::-;1919:48;;1713:260;;;;;:::o;2160:186::-;2219:6;2272:2;2260:9;2251:7;2247:23;2243:32;2240:52;;;2288:1;2285;2278:12;2240:52;2311:29;2330:9;2311:29;:::i;2351:329::-;2553:2;2535:21;;;2592:1;2572:18;;;2565:29;-1:-1:-1;;;2625:2:14;2610:18;;2603:36;2671:2;2656:18;;2351:329::o;3734:127::-;3795:10;3790:3;3786:20;3783:1;3776:31;3826:4;3823:1;3816:15;3850:4;3847:1;3840:15;3866:128;3933:9;;;3954:11;;;3951:37;;;3968:18;;:::i;3999:573::-;4117:4;4123:6;4183:11;4170:25;4277:2;4273:7;4262:8;4246:14;4242:29;4238:43;4218:18;4214:68;4204:96;;4296:1;4293;4286:12;4204:96;4323:33;;4375:20;;;-1:-1:-1;4418:18:14;4407:30;;4404:50;;;4450:1;4447;4440:12;4404:50;4483:4;4471:17;;-1:-1:-1;4542:4:14;4530:17;;4514:14;4510:38;4500:49;;4497:69;;;4562:1;4559;4552:12;5396:127;5457:10;5452:3;5448:20;5445:1;5438:31;5488:4;5485:1;5478:15;5512:4;5509:1;5502:15;6652:135;6691:3;6712:17;;;6709:43;;6732:18;;:::i;:::-;-1:-1:-1;6779:1:14;6768:13;;6652:135::o;8946:125::-;9011:9;;;9032:10;;;9029:36;;;9045:18;;:::i;9437:127::-;9498:10;9493:3;9489:20;9486:1;9479:31;9529:4;9526:1;9519:15;9553:4;9550:1;9543:15;9991:543;10209:13;;10152:3;;10183;;10262:4;10289:15;;;10152:3;10332:175;10346:6;10343:1;10340:13;10332:175;;;10409:13;;10395:28;;10445:14;;;;10482:15;;;;10368:1;10361:9;10332:175;;;-1:-1:-1;10523:5:14;;9991:543;-1:-1:-1;;;;;;9991:543:14:o;11540:521::-;11617:4;11623:6;11683:11;11670:25;11777:2;11773:7;11762:8;11746:14;11742:29;11738:43;11718:18;11714:68;11704:96;;11796:1;11793;11786:12;11704:96;11823:33;;11875:20;;;-1:-1:-1;11918:18:14;11907:30;;11904:50;;;11950:1;11947;11940:12;11904:50;11983:4;11971:17;;-1:-1:-1;12014:14:14;12010:27;;;12000:38;;11997:58;;;12051:1;12048;12041:12;12397:407;12599:2;12581:21;;;12638:2;12618:18;;;12611:30;12677:34;12672:2;12657:18;;12650:62;-1:-1:-1;;;12743:2:14;12728:18;;12721:41;12794:3;12779:19;;12397:407::o;12809:277::-;12876:6;12929:2;12917:9;12908:7;12904:23;12900:32;12897:52;;;12945:1;12942;12935:12;12897:52;12977:9;12971:16;13030:5;13023:13;13016:21;13009:5;13006:32;12996:60;;13052:1;13049;13042:12;13502:127;13563:10;13558:3;13554:20;13551:1;13544:31;13594:4;13591:1;13584:15;13618:4;13615:1;13608:15;15157:250;15242:1;15252:113;15266:6;15263:1;15260:13;15252:113;;;15342:11;;;15336:18;15323:11;;;15316:39;15288:2;15281:10;15252:113;;;-1:-1:-1;;15399:1:14;15381:16;;15374:27;15157:250::o;15412:287::-;15541:3;15579:6;15573:13;15595:66;15654:6;15649:3;15642:4;15634:6;15630:17;15595:66;:::i;:::-;15677:16;;;;;15412:287;-1:-1:-1;;15412:287:14:o;16465:396::-;16614:2;16603:9;16596:21;16577:4;16646:6;16640:13;16689:6;16684:2;16673:9;16669:18;16662:34;16705:79;16777:6;16772:2;16761:9;16757:18;16752:2;16744:6;16740:15;16705:79;:::i;:::-;16845:2;16824:15;-1:-1:-1;;16820:29:14;16805:45;;;;16852:2;16801:54;;16465:396;-1:-1:-1;;16465:396:14:o
Swarm Source
ipfs://41efa89b6ae4caa9b63acb1e36a71e523ed1a04d6687b60e4da7e61aa589f215
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.