Overview
APE Balance
80.737311225164482354 APE
APE Value
$100.48 (@ $1.24/APE)More Info
Private Name Tags
ContractCreator
Latest 9 from a total of 9 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Erc721Airdrop | 7357307 | 2 days ago | IN | 10 APE | 0.49544683 | ||||
Erc721Airdrop | 7228035 | 6 days ago | IN | 10 APE | 0.0949315 | ||||
Erc721Airdrop | 7204883 | 6 days ago | IN | 10 APE | 0.63313139 | ||||
Erc721Airdrop | 7204869 | 6 days ago | IN | 10 APE | 0.69028612 | ||||
Erc721Airdrop | 6756519 | 16 days ago | IN | 10 APE | 0.39198566 | ||||
Erc721Airdrop | 5018401 | 40 days ago | IN | 10 APE | 0.06871812 | ||||
Erc721Airdrop | 3402438 | 58 days ago | IN | 10 APE | 0.02792884 | ||||
Erc721Airdrop | 3402400 | 58 days ago | IN | 10 APE | 0.68502574 | ||||
Initialize | 748008 | 71 days ago | IN | 0 APE | 0.00741592 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
SlashTokenApe
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 9999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.23; // pragma solidity 0.8.19; import "../handshake-drop-libs/TokenTransferer.sol"; import "../handshake-drop-types/interfaces/SlashTokenEvents.sol"; import "../handshake-drop-libs/NativeTransferer.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "../handshake-drop-libs/SubscriptionRegistry.sol"; interface ArbInfo { function configureAutomaticYield() external; function configureVoidYield() external; function configureDelegateYield(address delegate) external; } /// @author 0xCocomastoras /// @custom:version 1.0 /// @title SlashToken /// @notice SlashToken is a simple, yet powerful tool to airdrop tokens and NFTs. contract SlashTokenApe is TokenTransferer, NativeTransferer, SlashTokenEvents, SubscriptionRegistry, ReentrancyGuard { constructor() ReentrancyGuard(){ ArbInfo(0x0000000000000000000000000000000000000065).configureAutomaticYield(); } /** @notice ERC-20 token airdrop with same, equal amount to all recipients @param recipients A list of addresses of the recipients @param amount Amount of tokens each recipient will be airdropped @param token Address of the token */ function erc20AirdropEqualAmount(address[] calldata recipients, uint256 amount, address token) external payable nonReentrant { require(frozen == 0, "CF"); require(denylist[msg.sender] == 0, 'UD'); uint256 value = _getBaseFeeForWallet(); //Check if wallet is whitelisted with different value uint256 purchasedTxns = _getAvailableTxnsForWallet(); uint recipientsLength = recipients.length; value = value == 0 ? baseFee : value; if (purchasedTxns == 0) { require(msg.value == value, "NVV"); } else { _updateAvailableTxnsForWallet(); } require(isInitialized != 0, 'NIY'); require(recipientsLength <= 500, 'NVL'); uint recipientsOffset; assembly { recipientsOffset := recipients.offset } _performMultiERC20Transfer(token, recipientsOffset, recipientsLength, amount); emit Erc20AirdropEqualAmount(msg.sender, token, recipientsLength, recipientsLength*amount); } /** @notice ERC-20 token airdrop with custom amount for each recipient @param recipients A list of addresses of the recipients @param amount A list of amounts of the tokens each recipient will be airdropped @param token Address of the token @param totalAmount The sum of all tokens to be airdropped */ function erc20AirdropCustomAmount(address[] calldata recipients, uint256[] calldata amount, address token, uint256 totalAmount) external payable nonReentrant { require(frozen == 0, "CF"); require(denylist[msg.sender] == 0, 'UD'); uint256 value = _getBaseFeeForWallet(); //Check if wallet is whitelisted with different value uint256 purchasedTxns = _getAvailableTxnsForWallet(); uint recipientsLength = recipients.length; value = value == 0 ? baseFee : value; if (purchasedTxns == 0) { require(msg.value == value, "NVV"); } else { _updateAvailableTxnsForWallet(); } require(isInitialized != 0, 'NIY'); require(recipientsLength <= 500 && recipientsLength == amount.length, 'NVL'); uint recipientsOffset; uint amountsOffset; assembly { recipientsOffset := recipients.offset amountsOffset := amount.offset } _performMultiERC20TransferCustom(token, recipientsOffset, recipientsLength, amountsOffset, totalAmount); emit Erc20AirdropCustomAmount(msg.sender, token, recipientsLength, totalAmount); } /** @notice Native currency airdrop with same, equal amount to all recipients @param recipients A list of addresses of the recipients @param amount Amount of tokens each recipient will be airdropped */ function nativeAirdropEqualAmount(address[] calldata recipients, uint256 amount) external payable nonReentrant { require(frozen == 0, "CF"); require(isInitialized != 0, 'NIY'); require(denylist[msg.sender] == 0, 'UD'); uint recipientsOffset; uint recipientsLength = recipients.length; uint256 value = _getBaseFeeForWallet(); //Check if wallet is whitelisted with different value uint256 purchasedTxns = _getAvailableTxnsForWallet(); uint256 recipientsValue = amount * recipientsLength; value = value == 0 ? (baseFee + recipientsValue) : (value + recipientsValue); if (purchasedTxns == 0) { require(msg.value == value, "NVV"); } else { require(msg.value == recipientsValue, 'NVV'); _updateAvailableTxnsForWallet(); } require(recipientsLength <= 500, 'NVL'); assembly { recipientsOffset := recipients.offset } _performMultiNativeTransfer(recipientsOffset, recipientsLength, amount); emit NativeAirdropEqualAmount(msg.sender, recipientsLength, recipientsValue); } /** @notice Native currency airdrop with custom amount for each recipient @param recipients A list of addresses of the recipients @param amounts A list of amounts that each recipient will be airdropped */ function nativeAirdropCustomAmount(address[] calldata recipients, uint256[] calldata amounts) external payable nonReentrant { require(frozen == 0, "CF"); require(isInitialized != 0, 'NIY'); require(denylist[msg.sender] == 0, 'UD'); uint256 value = _getBaseFeeForWallet(); //Check if wallet is whitelisted with different value uint256 purchasedTxns = _getAvailableTxnsForWallet(); uint recipientsOffset; uint amountsOffset; uint recipientsLength = recipients.length; require(recipientsLength <= 500 && recipientsLength == amounts.length, 'NVL'); assembly { recipientsOffset := recipients.offset amountsOffset := amounts.offset } uint totalAmount = _performMultiNativeTransferCustom(recipientsOffset, recipientsLength, amountsOffset); value = value == 0 ? (baseFee + totalAmount) : (value + totalAmount); if (purchasedTxns == 0) { require(msg.value == value, "NVV"); } else { require(msg.value == totalAmount, 'NVV'); _updateAvailableTxnsForWallet(); } emit NativeAirdropCustomAmount(msg.sender, recipientsLength, totalAmount); } /** @notice Basic Airdrop of Erc721 tokens without bundle @param recipients A list of addresses of the recipients @param ids A list of ids of the token each recipient will be airdropped @param token The address of the token */ function erc721Airdrop(address[] calldata recipients, uint256[] calldata ids, address token) external payable nonReentrant { require(permitErc721 != 0, 'NEY'); require(frozen == 0, "CF"); require(isInitialized != 0, 'NIY'); require(denylist[msg.sender] == 0, 'UD'); uint256 value = _getBaseFeeForWallet(); value = value == 0 ? baseFee : value; uint256 purchasedTxns = _getAvailableTxnsForWallet(); uint recipientsLength = recipients.length; if (purchasedTxns == 0) { require(msg.value == value, "NVV"); } else { _updateAvailableTxnsForWallet(); } require(recipientsLength <= 500 && recipientsLength == ids.length, 'NVL'); uint recipientsOffset; uint idsOffset; assembly { recipientsOffset := recipients.offset idsOffset := ids.offset } _performMultiERC721Transfer(token, msg.sender, recipientsOffset, recipientsLength, idsOffset); emit Erc721Airdrop(msg.sender, token, recipientsLength); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; contract ManagerActions{ constructor(){} address owner; address feeSink; uint256 public frozen; uint256 public permitErc721 = 1; mapping(address => uint256) denylist; using EnumerableSet for EnumerableSet.AddressSet; EnumerableSet.AddressSet deniedAddresses; /** @notice Admin freezes / unfreezes contracts @param value_ 0 = unfreeze, any other value = freeze */ function freezeContract(uint256 value_) external { require(msg.sender == owner, 'NVS'); frozen = value_; } /** @notice Admin permits/freezes erv721Airdrops @param value_ 0 = freeze, any other value = permit */ function handleErc721Flag(uint256 value_) external { require(msg.sender == owner, 'NVS'); permitErc721 = value_; } /** @notice Admin updates fee sink address @param feeSink_ The new fee sink address */ function updateFeeSink(address feeSink_) external { require(msg.sender == owner, 'NVS'); feeSink = feeSink_; } /** @notice Admin claims contract fees */ function claimFees() external { address owner_ = owner; assembly { if iszero(eq(caller(), owner_)) { revert(0,0) } if iszero(call(gas(), sload(feeSink.slot), selfbalance(), 0, 0, 0, 0)) { revert(0,0) } } } function addToDenylist(address[] memory list) external { require(msg.sender == owner, 'NVS'); uint len = list.length; for(uint i = 0; i < len;) { if (!deniedAddresses.contains(list[i])) { deniedAddresses.add(list[i]); } unchecked { denylist[list[i]] = 1; i++; } } } function removeFromDenylist(address[] memory list) external { require(msg.sender == owner, 'NVS'); uint len = list.length; for(uint i = 0; i < len;) { if (deniedAddresses.contains(list[i])) { deniedAddresses.remove(list[i]); } unchecked { denylist[list[i]] = 0; i++; } } } function getDenylist() external view returns (address[] memory) { require(msg.sender == owner, 'NVS'); return deniedAddresses.values(); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; contract NativeTransferer { uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /** * @dev Internal function to transfer native tokens from a given originator * to a multiple recipients * * @param offset Calldata offset of the recipients of the transfer. * @param length Calldata length of the recipients of the transfer. * @param amount The amount to transfer. */ function _performMultiNativeTransfer(uint256 offset, uint256 length, uint256 amount) internal { assembly { for { let i := 0 } lt(i, length) { i := add(i, 1) } { let to := calldataload(add(offset, mul(i, 0x20))) if iszero( call( GAS_STIPEND_NO_STORAGE_WRITES, to, amount, 0, 0, 0, 0 )) { revert(0,0) } } } } /** * @dev Internal function to transfer native tokens from a given originator * to a multiple recipients * * @param recipientsOffset Calldata offset of the recipients of the transfer. * @param length Calldata length of the recipients of the transfer. * @param amountsOffset Calldata offset of the amounts to transfer */ function _performMultiNativeTransferCustom(uint256 recipientsOffset, uint256 length, uint256 amountsOffset) internal returns (uint256 totalAmount){ assembly { for { let i := 0 } lt(i, length) { i := add(i, 1) } { let to := calldataload(add(recipientsOffset, mul(i, 0x20))) let amount := calldataload(add(amountsOffset, mul(i, 0x20))) totalAmount := add(totalAmount, amount) if iszero( call( GAS_STIPEND_NO_STORAGE_WRITES, to, amount, 0, 0, 0, 0 )) { revert(0,0) } } } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../handshake-drop-types/interfaces/SlashTokenRegistryEvents.sol"; import "../handshake-drop-types/interfaces/PremiumSubscriptionRegistryEvents.sol"; import "./ManagerActions.sol"; contract SubscriptionRegistry is SlashTokenRegistryEvents, PremiumSubscriptionRegistryEvents, ManagerActions { // @dev user's adddress to custom base fee for no bundle purchases mapping (address => uint256) baseFeeWhitelisted; // @dev user address to total available txns to use mapping(address => uint256) public userToTxns; uint256[] availableTxnsBundles; uint256[] txnsBundlesToPrice; uint256 isInitialized; uint256 public baseFee; using EnumerableSet for EnumerableSet.AddressSet; EnumerableSet.AddressSet bundleUsers; function initialize(address admin_, address feeSink_, uint256 baseFeeCostInWei, uint256[] memory availableTxnsBundles_, uint256[] memory txnsBundlesToPrice_ ) external { require(isInitialized == 0, 'AI'); require(availableTxnsBundles_.length == txnsBundlesToPrice_.length, 'NVD'); owner = admin_; feeSink = feeSink_; availableTxnsBundles = availableTxnsBundles_; txnsBundlesToPrice = txnsBundlesToPrice_; isInitialized = 1; baseFee = baseFeeCostInWei; } constructor(){} /** @notice User buys a bundle of txns @param bundleIndex The index of the bundle array @param quantity The number of bundles that the user wants to buy */ function buyTxnsBundle(uint256 bundleIndex, uint256 quantity) external payable { require(frozen == 0, "CF"); require(msg.value == txnsBundlesToPrice[bundleIndex] * quantity, 'NVV'); require(denylist[msg.sender] == 0, 'UD'); require(quantity != 0, 'NVA'); if(!bundleUsers.contains(msg.sender)) { bundleUsers.add(msg.sender); } uint256 total; unchecked { total = availableTxnsBundles[bundleIndex] * quantity; userToTxns[msg.sender] += total; } emit TxnsBundleBought(msg.sender, msg.value, total); } /** @notice Admin sets promo fee for wallet instead of default base fee @param wallet User's wallet address @param amountInWei New cost per txns */ function setBaseFeeForWallet(address wallet, uint256 amountInWei) external { require(amountInWei < baseFee, "NVV"); require(msg.sender == owner, 'NVS'); baseFeeWhitelisted[wallet] = amountInWei; emit WalletBaseFeeSet(wallet, amountInWei); } /** @notice Admin resets promo fee for wallet. Default base fee applies @param wallet User's wallet address */ function resetBaseFeeForWallet(address wallet) external { require(msg.sender == owner, 'NVS'); delete baseFeeWhitelisted[wallet]; emit WalletBaseFeeReset(wallet); } /** @notice Admin adds txns to a user @param wallets A list of user's wallet address @param txns A list of txns to be added */ function addTxnsToWallets(address[] memory wallets, uint256[] memory txns) external { require(msg.sender == owner, 'NVS'); require(wallets.length == txns.length, "NVL"); uint len = wallets.length; for(uint i =0; i<len;){ unchecked { userToTxns[wallets[i]] += txns[i]; i++; } } emit TxnsAdded(wallets, txns); } /** @notice Admin sets the new base fee for all txns @param baseFee_ New base fee */ function setNewBaseFee(uint256 baseFee_) external { require(msg.sender == owner, 'NVS'); baseFee = baseFee_; } /** @notice Admin sets the new available txnsBundles and prices @param availableTxnsBundles_ New available bundles @param txnsBundlesToPrice_ New price per bundles */ function updateBundles(uint256[] memory availableTxnsBundles_, uint256[] memory txnsBundlesToPrice_ ) external { require(msg.sender == owner, 'NVS'); require(availableTxnsBundles_.length == txnsBundlesToPrice_.length, 'NVD'); availableTxnsBundles = availableTxnsBundles_; txnsBundlesToPrice = txnsBundlesToPrice_; emit BundlesUpdated(msg.sender, availableTxnsBundles_, txnsBundlesToPrice_); } /** @notice External view function that returns active bundle offers */ function getBundles() external view returns (uint256[] memory AvailableBundles, uint256[] memory BundlesPrices) { AvailableBundles = availableTxnsBundles; BundlesPrices = txnsBundlesToPrice; } /** @notice External view function that returns the custom base fee for wallet */ function getBaseFeeForWallet() external view returns (uint256) { return baseFeeWhitelisted[msg.sender]; } /** @notice External view function that returns the available txns for wallet */ function getAvailableTxnsForWallet() external view returns (uint256) { return userToTxns[msg.sender]; } /** @notice External view function that returns all the users that have bought a bundle */ function getUsersThatBoughtBundles() external view returns (address[] memory Users) { require(msg.sender == owner, 'NVS'); Users = bundleUsers.values(); } /** @notice Internal view function that returns the custom base fee for wallet */ function _getBaseFeeForWallet() internal view returns (uint256) { return baseFeeWhitelisted[msg.sender]; } /** @notice Internal view function that returns the available txns for wallet */ function _updateAvailableTxnsForWallet() internal { unchecked { --userToTxns[msg.sender]; } } /** @notice Internal view function that returns the available txns for wallet */ function _getAvailableTxnsForWallet() internal view returns (uint256) { return userToTxns[msg.sender]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /// @notice Safe ERC20 ,ERC721 multi transfer library that gracefully handles missing return values. /// @author Cocomastoras /// @author Modified from Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// /// @dev Note: /// - For ERC20s and ERC721s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. contract TokenTransferer { error TransferFromFailed(); /** * @dev Internal function to transfer ERC20 tokens from a given originator * to a multiple recipients. Sufficient approvals must be set on the * contract performing the transfer. * * @param token The ERC20 token to transfer. * @param recipientsOffset Calldata offset of the recipients of the transfer. * @param length Calldata length of the recipients of the transfer. * @param amount The amount to transfer. */ function _performMultiERC20Transfer(address token, uint256 recipientsOffset, uint256 length, uint256 amount) internal{ /// @solidity memory-safe-assembly assembly { let total := mul(amount, length) let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, total) // Store the `amount` argument. mstore(0x40, address()) // Store the `to` argument. mstore(0x2c, shl(96, caller())) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. or( eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x40, amount) // Store the `amount` argument. for { let i := 0 } lt(i, length) { i := add(i, 1) } { let to := calldataload(add(recipientsOffset, mul(i, 0x20))) mstore(0x2c, shl(96, to)) // Store the `to` argument. mstore(0x0c, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /** * @dev Internal function to transfer ERC20 tokens from a given originator * to multiple recipients. Sufficient approvals must be set on the * contract performing the transfer. * @param token The ERC20 token to transfer. * @param recipientsOffset Offset of the recipients of the transfer. * @param recipientsLength Length of the recipients of the transfer. * @param amountsOffset Offset of the amounts to transfer. * @param totalAmount The totalAmount to transfer */ function _performMultiERC20TransferCustom(address token, uint256 recipientsOffset, uint256 recipientsLength, uint256 amountsOffset, uint256 totalAmount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, totalAmount) // Store the `amount` argument. mstore(0x40, address()) // Store the `to` argument. mstore(0x2c, shl(96, caller())) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. or( eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } let sumAmount := 0 for { let i := 0 } lt(i, recipientsLength) { i := add(i, 1) } { let to := calldataload(add(recipientsOffset, mul(i, 0x20))) let amount := calldataload(add(amountsOffset, mul(i, 0x20))) sumAmount := add(sumAmount, amount) mstore(0x40, amount) // Store the `amount` argument. mstore(0x2c, shl(96, to)) // Store the `to` argument. mstore(0x0c, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } } if iszero(eq(totalAmount, sumAmount)) { revert(0,0) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /** * @dev Internal function to transfer batch of ERC721 tokens from a given * originator to multiple recipients. Sufficient approvals must be set on * the contract performing the transfer. Note that this function does * not check whether the receiver can accept the ERC721 token (i.e. it * does not use `safeTransferFrom`). * * @param token The ERC721 token to transfer. * @param from The originator of the transfer. * @param recipientsOffset The offset of recipients of the transfer. * @param recipientsLength The length of tokens to transfer. * @param idsOffset The offset of tokenIds to transfer. */ function _performMultiERC721Transfer( address token, address from, uint256 recipientsOffset, uint256 recipientsLength, uint256 idsOffset ) internal { // Utilize assembly to perform an optimized ERC721 token transfer. assembly { let m := mload(0x40) // Cache the free memory pointer. for { let i := 0 } lt(i, recipientsLength) { i := add(i, 1) } { let to := calldataload(add(recipientsOffset, mul(i, 0x20))) let identifier := calldataload(add(idsOffset, mul(i, 0x20))) mstore(0x60, identifier) // Store the `identifier` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. iszero(returndatasize()), // Returned error. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x00) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface PremiumSubscriptionRegistryEvents { event WalletBaseFeeSet(address indexed Wallet, uint256 BaseFeeInWei); event WalletBaseFeeReset(address indexed Wallet); event TxnsAdded(address[] Wallet, uint256[] Txns); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface SlashTokenEvents { event Erc20AirdropEqualAmount(address indexed From, address indexed Token,uint256 RecipientsLength, uint256 TotalAmount); event Erc20AirdropCustomAmount(address indexed From, address indexed Token, uint256 RecipientsLength, uint256 TotalAmount); event NativeAirdropEqualAmount(address indexed From,uint256 RecipientsLength, uint256 TotalAmount); event NativeAirdropCustomAmount(address indexed From, uint256 RecipientsLength, uint256 TotalAmount); event Erc721Airdrop(address indexed From, address indexed Token, uint256 RecipientsLength); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface SlashTokenRegistryEvents { event TxnsBundleBought(address indexed Buyer, uint256 Amount, uint256 Txns); event BundlesUpdated(address indexed Operator, uint256[] BundlesAmounts, uint256[] BundlesPrices); }
{ "optimizer": { "enabled": true, "runs": 9999999 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"TransferFromFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"Operator","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"BundlesAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"BundlesPrices","type":"uint256[]"}],"name":"BundlesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"From","type":"address"},{"indexed":true,"internalType":"address","name":"Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"RecipientsLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TotalAmount","type":"uint256"}],"name":"Erc20AirdropCustomAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"From","type":"address"},{"indexed":true,"internalType":"address","name":"Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"RecipientsLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TotalAmount","type":"uint256"}],"name":"Erc20AirdropEqualAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"From","type":"address"},{"indexed":true,"internalType":"address","name":"Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"RecipientsLength","type":"uint256"}],"name":"Erc721Airdrop","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"From","type":"address"},{"indexed":false,"internalType":"uint256","name":"RecipientsLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TotalAmount","type":"uint256"}],"name":"NativeAirdropCustomAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"From","type":"address"},{"indexed":false,"internalType":"uint256","name":"RecipientsLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TotalAmount","type":"uint256"}],"name":"NativeAirdropEqualAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"Wallet","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"Txns","type":"uint256[]"}],"name":"TxnsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"Buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"Txns","type":"uint256"}],"name":"TxnsBundleBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"Wallet","type":"address"}],"name":"WalletBaseFeeReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"Wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"BaseFeeInWei","type":"uint256"}],"name":"WalletBaseFeeSet","type":"event"},{"inputs":[{"internalType":"address[]","name":"list","type":"address[]"}],"name":"addToDenylist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint256[]","name":"txns","type":"uint256[]"}],"name":"addTxnsToWallets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleIndex","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"buyTxnsBundle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amount","type":"uint256[]"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"erc20AirdropCustomAmount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"erc20AirdropEqualAmount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"token","type":"address"}],"name":"erc721Airdrop","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"freezeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableTxnsForWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseFeeForWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBundles","outputs":[{"internalType":"uint256[]","name":"AvailableBundles","type":"uint256[]"},{"internalType":"uint256[]","name":"BundlesPrices","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDenylist","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUsersThatBoughtBundles","outputs":[{"internalType":"address[]","name":"Users","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"handleErc721Flag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"feeSink_","type":"address"},{"internalType":"uint256","name":"baseFeeCostInWei","type":"uint256"},{"internalType":"uint256[]","name":"availableTxnsBundles_","type":"uint256[]"},{"internalType":"uint256[]","name":"txnsBundlesToPrice_","type":"uint256[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"nativeAirdropCustomAmount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"nativeAirdropEqualAmount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"permitErc721","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"list","type":"address[]"}],"name":"removeFromDenylist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"resetBaseFeeForWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amountInWei","type":"uint256"}],"name":"setBaseFeeForWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseFee_","type":"uint256"}],"name":"setNewBaseFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"availableTxnsBundles_","type":"uint256[]"},{"internalType":"uint256[]","name":"txnsBundlesToPrice_","type":"uint256[]"}],"name":"updateBundles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeSink_","type":"address"}],"name":"updateFeeSink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userToTxns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600160035534801561001557600080fd5b506001600f8190555060656001600160a01b0316637114177a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561005a57600080fd5b505af115801561006e573d6000803e3d6000fd5b50505050613292806100816000396000f3fe6080604052600436106101ac5760003560e01c80636ef25c3a116100ec57806393f9e6f91161008a578063d294f09311610064578063d294f09314610438578063d993cdff1461044d578063e85ddb8a1461047a578063fe7009901461049a57600080fd5b806393f9e6f9146103ed5780639d07a40b14610402578063cddfa1a41461042257600080fd5b80638634fd24116100c65780638634fd241461039457806388f941e8146103a75780638a6ff456146103ba5780638fc8b3b2146103da57600080fd5b80636ef25c3a1461033c5780637850953d14610352578063798ed83d1461037457600080fd5b806333f740a111610159578063586668061161013357806358666806146102e357806362274c2b146102f65780636b55040f146103165780636c11d85a1461032957600080fd5b806333f740a11461028157806334ae8e38146102a157806347ec4ed1146102c157600080fd5b8063244bd9671161018a578063244bd9671461021f578063286ddb681461024157806331fd0d7e1461026157600080fd5b8063054f7d9c146101b157806320a225cb146101da57806322f10e2f146101fd575b600080fd5b3480156101bd57600080fd5b506101c760025481565b6040519081526020015b60405180910390f35b3480156101e657600080fd5b506101ef6104ba565b6040516101d1929190612b05565b34801561020957600080fd5b5061021d610218366004612b33565b610567565b005b34801561022b57600080fd5b50336000908152600860205260409020546101c7565b34801561024d57600080fd5b5061021d61025c366004612b33565b6105f2565b34801561026d57600080fd5b5061021d61027c366004612b33565b610678565b34801561028d57600080fd5b5061021d61029c366004612b75565b6106fe565b3480156102ad57600080fd5b5061021d6102bc366004612cb0565b610850565b3480156102cd57600080fd5b50336000908152600760205260409020546101c7565b61021d6102f1366004612d60565b6109ac565b34801561030257600080fd5b5061021d610311366004612dcc565b610d3b565b61021d610324366004612de7565b610e0d565b61021d610337366004612e70565b611131565b34801561034857600080fd5b506101c7600c5481565b34801561035e57600080fd5b506103676114c9565b6040516101d19190612f38565b34801561038057600080fd5b5061021d61038f366004612fb1565b61155c565b61021d6103a2366004612fee565b6116a0565b61021d6103b536600461304b565b6119b7565b3480156103c657600080fd5b5061021d6103d5366004612fb1565b611c2c565b61021d6103e836600461306d565b611d54565b3480156103f957600080fd5b506103676120ef565b34801561040e57600080fd5b5061021d61041d3660046130b9565b61217d565b34801561042e57600080fd5b506101c760035481565b34801561044457600080fd5b5061021d6122dd565b34801561045957600080fd5b506101c7610468366004612dcc565b60086020526000908152604090205481565b34801561048657600080fd5b5061021d610495366004613148565b61231a565b3480156104a657600080fd5b5061021d6104b5366004612dcc565b6124c1565b606080600980548060200260200160405190810160405280929190818152602001828054801561050957602002820191906000526020600020905b8154815260200190600101908083116104f5575b50505050509150600a80548060200260200160405190810160405280929190818152602001828054801561055c57602002820191906000526020600020905b815481526020019060010190808311610548575b505050505090509091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600c55565b60005473ffffffffffffffffffffffffffffffffffffffff163314610673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600255565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600355565b600c548110610769576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b73ffffffffffffffffffffffffffffffffffffffff821660008181526007602052604090819020839055517f44784c405393a593553ed0bf0ddb15aa2494ba9b97a8d75dfc9fabb7a64c8ce5906108449084815260200190565b60405180910390a25050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805182511461093c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5644000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b815161094f906009906020850190612a69565b50805161096390600a906020840190612a69565b503373ffffffffffffffffffffffffffffffffffffffff167fed68a7a2289c86234d260dc96066680ff0bcde7d3376a219df515dde860435b18383604051610844929190612b05565b6109b4612589565b60025415610a1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b54600003610a8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415610b01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b336000908152600760209081526040808320546008909252822054909180866101f48111801590610b3157508086145b610b97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8892508691506000610baa8483856125cc565b90508515610bc157610bbc81876131ae565b610bcf565b80600c54610bcf91906131ae565b955084600003610c4757853414610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610cea565b803414610cb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610cea33600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b604080518381526020810183905233917f2c7cd2d52efdb7bcb324ce1fdaad584211503edbbf94fa7a3fde2624da572642910160405180910390a2505050505050610d356001600f55565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260076020526040808220829055517f9a93cb5054fe47b6e8ec0e29a26edd6249309d823eccab337b5c81dda65f6ddc9190a250565b610e15612589565b60025415610e7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415610ef6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260076020908152604080832054600890925290912054868215610f1f5782610f23565b600c545b925081600003610f9b57823414610f96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610fd5565b610fd533600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b600b54600003611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6101f4811115801561105257508086145b6110b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b88876110c7878385848a61260f565b604080518481526020810188905273ffffffffffffffffffffffffffffffffffffffff89169133917f0e18fd6025578556afc2d4c83f1e98be2ddb206457774fa37a3a8b1605ad6f79910160405180910390a350505050506111296001600f55565b505050505050565b611139612589565b6003546000036111a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4559000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6002541561120f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b5460000361127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260046020526040902054156112f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260076020526040902054801561130e5780611312565b600c545b9050600061132c3360009081526008602052604090205490565b90508560008290036113a6578234146113a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6113e0565b6113e033600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b6101f481111580156113f157508085145b611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b878661146686338486856126e6565b60405183815273ffffffffffffffffffffffffffffffffffffffff87169033907f4bd386a75bd69ced877c29ffb9d2058eeed770d425c9027116b45e6f0fb4645a9060200160405180910390a350505050506114c26001600f55565b5050505050565b60005460609073ffffffffffffffffffffffffffffffffffffffff16331461154d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611557600d61274a565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805160005b8181101561169b576116178382815181106115ff576115ff6131c1565b6020026020010151600561275e90919063ffffffff16565b61164a57611648838281518110611630576116306131c1565b6020026020010151600561279290919063ffffffff16565b505b600160046000858481518110611662576116626131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020556001016115e2565b505050565b6116a8612589565b60025415611712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b336000908152600760209081526040808320546008909252909120548482156117b257826117b6565b600c545b92508160000361182e57823414611829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611868565b61186833600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b600b546000036118d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6101f4811115611940576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8661194d858284896127b4565b73ffffffffffffffffffffffffffffffffffffffff8516337fbfc5bd893849e5d9bf1ac87d7e1fcec4f9afece75f87062d0c2370f1c6b5734b846119918a826131f0565b6040805192835260208301919091520160405180910390a350505050610d356001600f55565b60025415611a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b80600a8381548110611a3557611a356131c1565b9060005260206000200154611a4a91906131f0565b3414611ab2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611b29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b80600003611b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5641000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611b9e600d3361275e565b611baf57611bad600d33612792565b505b60008160098481548110611bc557611bc56131c1565b600091825260208083209190910154338084526008835260409384902080549590920294850190915582513481529182018490529293507f3686dd4aa3f7c95dcac2734a95dcdcf29641e7e3f71f6ea1b39bc6bea5e36385910160405180910390a2505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805160005b8181101561169b57611ccf8382815181106115ff576115ff6131c1565b15611d0357611d01838281518110611ce957611ce96131c1565b6020026020010151600561287990919063ffffffff16565b505b600060046000858481518110611d1b57611d1b6131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002055600101611cb2565b611d5c612589565b60025415611dc6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b54600003611e32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611ea9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b60008281611ec33360009081526007602052604090205490565b90506000611edd3360009081526008602052604090205490565b90506000611eeb84876131f0565b90508215611f0257611efd81846131ae565b611f10565b80600c54611f1091906131ae565b925081600003611f8857823414611f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b61202b565b803414611ff1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b61202b33600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b6101f4841115612097576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8794506120a585858861289b565b604080518581526020810183905233917fca9fd6c3fcc68235a3c738db806875a8e98e0bcb25f11f56860971296c6de997910160405180910390a2505050505061169b6001600f55565b60005460609073ffffffffffffffffffffffffffffffffffffffff163314612173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611557600561274a565b600b54156121e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f414900000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8051825114612252576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5644000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6000805473ffffffffffffffffffffffffffffffffffffffff8088167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255600180549287169290911691909117905581516122ba906009906020850190612a69565b5080516122ce90600a906020840190612a69565b50506001600b5550600c555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633811461230257600080fd5b600080600080476001545af161231757600080fd5b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461239b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8051825114612406576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b815160005b8181101561248257828181518110612425576124256131c1565b602002602001015160086000868481518110612443576124436131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000208054909101905560010161240b565b507f590a1a0c22d6042324e10baeee375e32704843a4630e1cc9889e30170a5a2efa83836040516124b4929190613207565b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6002600f54036125c5576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600f55565b6000805b83811015612607576020810283810135928301929086013590600080808084866108fcf16125fd57600080fd5b50506001016125d0565b509392505050565b60405181606052306040523360601b602c526f23b872dd000000000000000000000000600c52602060006064601c60008a5af13d15600160005114171661265e57637939f4246000526004601cfd5b6000805b858110156126c95760208181028681013560408190529089013560601b602c526fa9059cbb000000000000000000000000600c52929092019160006044601c828c5af13d1560016000511417166126c157637939f4246000526004601cfd5b600101612662565b508083146126d657600080fd5b5060006060526040525050505050565b60405160005b838110156126d657602081028381013560609081529086013560405286901b602c526f23b872dd000000000000000000000000600c526000806064601c828b5af13d151661274257637939f4246000526004601cfd5b6001016126ec565b60606000612757836128cb565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b90505b92915050565b60006127898373ffffffffffffffffffffffffffffffffffffffff8416612927565b81810260405181606052306040523360601b602c526f23b872dd000000000000000000000000600c52602060006064601c60008a5af13d15600160005114171661280657637939f4246000526004601cfd5b82604052600091505b8382101561286a57602082810286013560601b602c526fa9059cbb000000000000000000000000600c5260006044601c828a5af13d15600160005114171661285f57637939f4246000526004601cfd5b60018201915061280f565b60006060526040525050505050565b60006127898373ffffffffffffffffffffffffffffffffffffffff8416612976565b60005b82811015610d35576020810284013560008060008086856108fcf16128c257600080fd5b5060010161289e565b60608160000180548060200260200160405190810160405280929190818152602001828054801561291b57602002820191906000526020600020905b815481526020019060010190808311612907575b50505050509050919050565b600081815260018301602052604081205461296e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561278c565b50600061278c565b60008181526001830160205260408120548015612a5f57600061299a60018361321a565b85549091506000906129ae9060019061321a565b9050808214612a135760008660000182815481106129ce576129ce6131c1565b90600052602060002001549050808760000184815481106129f1576129f16131c1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612a2457612a2461322d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061278c565b600091505061278c565b828054828255906000526020600020908101928215612aa4579160200282015b82811115612aa4578251825591602001919060010190612a89565b50612ab0929150612ab4565b5090565b5b80821115612ab05760008155600101612ab5565b60008151808452602080850194506020840160005b83811015612afa57815187529582019590820190600101612ade565b509495945050505050565b604081526000612b186040830185612ac9565b8281036020840152612b2a8185612ac9565b95945050505050565b600060208284031215612b4557600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b7057600080fd5b919050565b60008060408385031215612b8857600080fd5b612b9183612b4c565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612c1557612c15612b9f565b604052919050565b600067ffffffffffffffff821115612c3757612c37612b9f565b5060051b60200190565b600082601f830112612c5257600080fd5b81356020612c67612c6283612c1d565b612bce565b8083825260208201915060208460051b870101935086841115612c8957600080fd5b602086015b84811015612ca55780358352918301918301612c8e565b509695505050505050565b60008060408385031215612cc357600080fd5b823567ffffffffffffffff80821115612cdb57600080fd5b612ce786838701612c41565b93506020850135915080821115612cfd57600080fd5b50612d0a85828601612c41565b9150509250929050565b60008083601f840112612d2657600080fd5b50813567ffffffffffffffff811115612d3e57600080fd5b6020830191508360208260051b8501011115612d5957600080fd5b9250929050565b60008060008060408587031215612d7657600080fd5b843567ffffffffffffffff80821115612d8e57600080fd5b612d9a88838901612d14565b90965094506020870135915080821115612db357600080fd5b50612dc087828801612d14565b95989497509550505050565b600060208284031215612dde57600080fd5b61278982612b4c565b60008060008060008060808789031215612e0057600080fd5b863567ffffffffffffffff80821115612e1857600080fd5b612e248a838b01612d14565b90985096506020890135915080821115612e3d57600080fd5b50612e4a89828a01612d14565b9095509350612e5d905060408801612b4c565b9150606087013590509295509295509295565b600080600080600060608688031215612e8857600080fd5b853567ffffffffffffffff80821115612ea057600080fd5b612eac89838a01612d14565b90975095506020880135915080821115612ec557600080fd5b50612ed288828901612d14565b9094509250612ee5905060408701612b4c565b90509295509295909350565b60008151808452602080850194506020840160005b83811015612afa57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612f06565b6020815260006127896020830184612ef1565b600082601f830112612f5c57600080fd5b81356020612f6c612c6283612c1d565b8083825260208201915060208460051b870101935086841115612f8e57600080fd5b602086015b84811015612ca557612fa481612b4c565b8352918301918301612f93565b600060208284031215612fc357600080fd5b813567ffffffffffffffff811115612fda57600080fd5b612fe684828501612f4b565b949350505050565b6000806000806060858703121561300457600080fd5b843567ffffffffffffffff81111561301b57600080fd5b61302787828801612d14565b9095509350506020850135915061304060408601612b4c565b905092959194509250565b6000806040838503121561305e57600080fd5b50508035926020909101359150565b60008060006040848603121561308257600080fd5b833567ffffffffffffffff81111561309957600080fd5b6130a586828701612d14565b909790965060209590950135949350505050565b600080600080600060a086880312156130d157600080fd5b6130da86612b4c565b94506130e860208701612b4c565b935060408601359250606086013567ffffffffffffffff8082111561310c57600080fd5b61311889838a01612c41565b9350608088013591508082111561312e57600080fd5b5061313b88828901612c41565b9150509295509295909350565b6000806040838503121561315b57600080fd5b823567ffffffffffffffff8082111561317357600080fd5b612ce786838701612f4b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561278c5761278c61317f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808202811582820484141761278c5761278c61317f565b604081526000612b186040830185612ef1565b8181038181111561278c5761278c61317f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212208b5ead1c3459024e0298de68a5894ce5dc1f53598e590c486cbda8946448061d64736f6c63430008170033
Deployed Bytecode
0x6080604052600436106101ac5760003560e01c80636ef25c3a116100ec57806393f9e6f91161008a578063d294f09311610064578063d294f09314610438578063d993cdff1461044d578063e85ddb8a1461047a578063fe7009901461049a57600080fd5b806393f9e6f9146103ed5780639d07a40b14610402578063cddfa1a41461042257600080fd5b80638634fd24116100c65780638634fd241461039457806388f941e8146103a75780638a6ff456146103ba5780638fc8b3b2146103da57600080fd5b80636ef25c3a1461033c5780637850953d14610352578063798ed83d1461037457600080fd5b806333f740a111610159578063586668061161013357806358666806146102e357806362274c2b146102f65780636b55040f146103165780636c11d85a1461032957600080fd5b806333f740a11461028157806334ae8e38146102a157806347ec4ed1146102c157600080fd5b8063244bd9671161018a578063244bd9671461021f578063286ddb681461024157806331fd0d7e1461026157600080fd5b8063054f7d9c146101b157806320a225cb146101da57806322f10e2f146101fd575b600080fd5b3480156101bd57600080fd5b506101c760025481565b6040519081526020015b60405180910390f35b3480156101e657600080fd5b506101ef6104ba565b6040516101d1929190612b05565b34801561020957600080fd5b5061021d610218366004612b33565b610567565b005b34801561022b57600080fd5b50336000908152600860205260409020546101c7565b34801561024d57600080fd5b5061021d61025c366004612b33565b6105f2565b34801561026d57600080fd5b5061021d61027c366004612b33565b610678565b34801561028d57600080fd5b5061021d61029c366004612b75565b6106fe565b3480156102ad57600080fd5b5061021d6102bc366004612cb0565b610850565b3480156102cd57600080fd5b50336000908152600760205260409020546101c7565b61021d6102f1366004612d60565b6109ac565b34801561030257600080fd5b5061021d610311366004612dcc565b610d3b565b61021d610324366004612de7565b610e0d565b61021d610337366004612e70565b611131565b34801561034857600080fd5b506101c7600c5481565b34801561035e57600080fd5b506103676114c9565b6040516101d19190612f38565b34801561038057600080fd5b5061021d61038f366004612fb1565b61155c565b61021d6103a2366004612fee565b6116a0565b61021d6103b536600461304b565b6119b7565b3480156103c657600080fd5b5061021d6103d5366004612fb1565b611c2c565b61021d6103e836600461306d565b611d54565b3480156103f957600080fd5b506103676120ef565b34801561040e57600080fd5b5061021d61041d3660046130b9565b61217d565b34801561042e57600080fd5b506101c760035481565b34801561044457600080fd5b5061021d6122dd565b34801561045957600080fd5b506101c7610468366004612dcc565b60086020526000908152604090205481565b34801561048657600080fd5b5061021d610495366004613148565b61231a565b3480156104a657600080fd5b5061021d6104b5366004612dcc565b6124c1565b606080600980548060200260200160405190810160405280929190818152602001828054801561050957602002820191906000526020600020905b8154815260200190600101908083116104f5575b50505050509150600a80548060200260200160405190810160405280929190818152602001828054801561055c57602002820191906000526020600020905b815481526020019060010190808311610548575b505050505090509091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600c55565b60005473ffffffffffffffffffffffffffffffffffffffff163314610673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600255565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600355565b600c548110610769576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b73ffffffffffffffffffffffffffffffffffffffff821660008181526007602052604090819020839055517f44784c405393a593553ed0bf0ddb15aa2494ba9b97a8d75dfc9fabb7a64c8ce5906108449084815260200190565b60405180910390a25050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805182511461093c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5644000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b815161094f906009906020850190612a69565b50805161096390600a906020840190612a69565b503373ffffffffffffffffffffffffffffffffffffffff167fed68a7a2289c86234d260dc96066680ff0bcde7d3376a219df515dde860435b18383604051610844929190612b05565b6109b4612589565b60025415610a1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b54600003610a8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415610b01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b336000908152600760209081526040808320546008909252822054909180866101f48111801590610b3157508086145b610b97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8892508691506000610baa8483856125cc565b90508515610bc157610bbc81876131ae565b610bcf565b80600c54610bcf91906131ae565b955084600003610c4757853414610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610cea565b803414610cb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610cea33600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b604080518381526020810183905233917f2c7cd2d52efdb7bcb324ce1fdaad584211503edbbf94fa7a3fde2624da572642910160405180910390a2505050505050610d356001600f55565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260076020526040808220829055517f9a93cb5054fe47b6e8ec0e29a26edd6249309d823eccab337b5c81dda65f6ddc9190a250565b610e15612589565b60025415610e7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415610ef6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260076020908152604080832054600890925290912054868215610f1f5782610f23565b600c545b925081600003610f9b57823414610f96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b610fd5565b610fd533600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b600b54600003611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6101f4811115801561105257508086145b6110b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b88876110c7878385848a61260f565b604080518481526020810188905273ffffffffffffffffffffffffffffffffffffffff89169133917f0e18fd6025578556afc2d4c83f1e98be2ddb206457774fa37a3a8b1605ad6f79910160405180910390a350505050506111296001600f55565b505050505050565b611139612589565b6003546000036111a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4559000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6002541561120f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b5460000361127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260046020526040902054156112f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b33600090815260076020526040902054801561130e5780611312565b600c545b9050600061132c3360009081526008602052604090205490565b90508560008290036113a6578234146113a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6113e0565b6113e033600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b6101f481111580156113f157508085145b611457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b878661146686338486856126e6565b60405183815273ffffffffffffffffffffffffffffffffffffffff87169033907f4bd386a75bd69ced877c29ffb9d2058eeed770d425c9027116b45e6f0fb4645a9060200160405180910390a350505050506114c26001600f55565b5050505050565b60005460609073ffffffffffffffffffffffffffffffffffffffff16331461154d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611557600d61274a565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805160005b8181101561169b576116178382815181106115ff576115ff6131c1565b6020026020010151600561275e90919063ffffffff16565b61164a57611648838281518110611630576116306131c1565b6020026020010151600561279290919063ffffffff16565b505b600160046000858481518110611662576116626131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252810191909152604001600020556001016115e2565b505050565b6116a8612589565b60025415611712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611789576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b336000908152600760209081526040808320546008909252909120548482156117b257826117b6565b600c545b92508160000361182e57823414611829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611868565b61186833600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b600b546000036118d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6101f4811115611940576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8661194d858284896127b4565b73ffffffffffffffffffffffffffffffffffffffff8516337fbfc5bd893849e5d9bf1ac87d7e1fcec4f9afece75f87062d0c2370f1c6b5734b846119918a826131f0565b6040805192835260208301919091520160405180910390a350505050610d356001600f55565b60025415611a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b80600a8381548110611a3557611a356131c1565b9060005260206000200154611a4a91906131f0565b3414611ab2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611b29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b80600003611b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5641000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611b9e600d3361275e565b611baf57611bad600d33612792565b505b60008160098481548110611bc557611bc56131c1565b600091825260208083209190910154338084526008835260409384902080549590920294850190915582513481529182018490529293507f3686dd4aa3f7c95dcac2734a95dcdcf29641e7e3f71f6ea1b39bc6bea5e36385910160405180910390a2505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b805160005b8181101561169b57611ccf8382815181106115ff576115ff6131c1565b15611d0357611d01838281518110611ce957611ce96131c1565b6020026020010151600561287990919063ffffffff16565b505b600060046000858481518110611d1b57611d1b6131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002055600101611cb2565b611d5c612589565b60025415611dc6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f434600000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600b54600003611e32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e4959000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b3360009081526004602052604090205415611ea9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f554400000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b60008281611ec33360009081526007602052604090205490565b90506000611edd3360009081526008602052604090205490565b90506000611eeb84876131f0565b90508215611f0257611efd81846131ae565b611f10565b80600c54611f1091906131ae565b925081600003611f8857823414611f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b61202b565b803414611ff1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5656000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b61202b33600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055565b6101f4841115612097576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8794506120a585858861289b565b604080518581526020810183905233917fca9fd6c3fcc68235a3c738db806875a8e98e0bcb25f11f56860971296c6de997910160405180910390a2505050505061169b6001600f55565b60005460609073ffffffffffffffffffffffffffffffffffffffff163314612173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b611557600561274a565b600b54156121e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f414900000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8051825114612252576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5644000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b6000805473ffffffffffffffffffffffffffffffffffffffff8088167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255600180549287169290911691909117905581516122ba906009906020850190612a69565b5080516122ce90600a906020840190612a69565b50506001600b5550600c555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633811461230257600080fd5b600080600080476001545af161231757600080fd5b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461239b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b8051825114612406576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e564c000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b815160005b8181101561248257828181518110612425576124256131c1565b602002602001015160086000868481518110612443576124436131c1565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000208054909101905560010161240b565b507f590a1a0c22d6042324e10baeee375e32704843a4630e1cc9889e30170a5a2efa83836040516124b4929190613207565b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f4e5653000000000000000000000000000000000000000000000000000000000060448201526064016105e4565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6002600f54036125c5576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600f55565b6000805b83811015612607576020810283810135928301929086013590600080808084866108fcf16125fd57600080fd5b50506001016125d0565b509392505050565b60405181606052306040523360601b602c526f23b872dd000000000000000000000000600c52602060006064601c60008a5af13d15600160005114171661265e57637939f4246000526004601cfd5b6000805b858110156126c95760208181028681013560408190529089013560601b602c526fa9059cbb000000000000000000000000600c52929092019160006044601c828c5af13d1560016000511417166126c157637939f4246000526004601cfd5b600101612662565b508083146126d657600080fd5b5060006060526040525050505050565b60405160005b838110156126d657602081028381013560609081529086013560405286901b602c526f23b872dd000000000000000000000000600c526000806064601c828b5af13d151661274257637939f4246000526004601cfd5b6001016126ec565b60606000612757836128cb565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b90505b92915050565b60006127898373ffffffffffffffffffffffffffffffffffffffff8416612927565b81810260405181606052306040523360601b602c526f23b872dd000000000000000000000000600c52602060006064601c60008a5af13d15600160005114171661280657637939f4246000526004601cfd5b82604052600091505b8382101561286a57602082810286013560601b602c526fa9059cbb000000000000000000000000600c5260006044601c828a5af13d15600160005114171661285f57637939f4246000526004601cfd5b60018201915061280f565b60006060526040525050505050565b60006127898373ffffffffffffffffffffffffffffffffffffffff8416612976565b60005b82811015610d35576020810284013560008060008086856108fcf16128c257600080fd5b5060010161289e565b60608160000180548060200260200160405190810160405280929190818152602001828054801561291b57602002820191906000526020600020905b815481526020019060010190808311612907575b50505050509050919050565b600081815260018301602052604081205461296e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561278c565b50600061278c565b60008181526001830160205260408120548015612a5f57600061299a60018361321a565b85549091506000906129ae9060019061321a565b9050808214612a135760008660000182815481106129ce576129ce6131c1565b90600052602060002001549050808760000184815481106129f1576129f16131c1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612a2457612a2461322d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061278c565b600091505061278c565b828054828255906000526020600020908101928215612aa4579160200282015b82811115612aa4578251825591602001919060010190612a89565b50612ab0929150612ab4565b5090565b5b80821115612ab05760008155600101612ab5565b60008151808452602080850194506020840160005b83811015612afa57815187529582019590820190600101612ade565b509495945050505050565b604081526000612b186040830185612ac9565b8281036020840152612b2a8185612ac9565b95945050505050565b600060208284031215612b4557600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b7057600080fd5b919050565b60008060408385031215612b8857600080fd5b612b9183612b4c565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612c1557612c15612b9f565b604052919050565b600067ffffffffffffffff821115612c3757612c37612b9f565b5060051b60200190565b600082601f830112612c5257600080fd5b81356020612c67612c6283612c1d565b612bce565b8083825260208201915060208460051b870101935086841115612c8957600080fd5b602086015b84811015612ca55780358352918301918301612c8e565b509695505050505050565b60008060408385031215612cc357600080fd5b823567ffffffffffffffff80821115612cdb57600080fd5b612ce786838701612c41565b93506020850135915080821115612cfd57600080fd5b50612d0a85828601612c41565b9150509250929050565b60008083601f840112612d2657600080fd5b50813567ffffffffffffffff811115612d3e57600080fd5b6020830191508360208260051b8501011115612d5957600080fd5b9250929050565b60008060008060408587031215612d7657600080fd5b843567ffffffffffffffff80821115612d8e57600080fd5b612d9a88838901612d14565b90965094506020870135915080821115612db357600080fd5b50612dc087828801612d14565b95989497509550505050565b600060208284031215612dde57600080fd5b61278982612b4c565b60008060008060008060808789031215612e0057600080fd5b863567ffffffffffffffff80821115612e1857600080fd5b612e248a838b01612d14565b90985096506020890135915080821115612e3d57600080fd5b50612e4a89828a01612d14565b9095509350612e5d905060408801612b4c565b9150606087013590509295509295509295565b600080600080600060608688031215612e8857600080fd5b853567ffffffffffffffff80821115612ea057600080fd5b612eac89838a01612d14565b90975095506020880135915080821115612ec557600080fd5b50612ed288828901612d14565b9094509250612ee5905060408701612b4c565b90509295509295909350565b60008151808452602080850194506020840160005b83811015612afa57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612f06565b6020815260006127896020830184612ef1565b600082601f830112612f5c57600080fd5b81356020612f6c612c6283612c1d565b8083825260208201915060208460051b870101935086841115612f8e57600080fd5b602086015b84811015612ca557612fa481612b4c565b8352918301918301612f93565b600060208284031215612fc357600080fd5b813567ffffffffffffffff811115612fda57600080fd5b612fe684828501612f4b565b949350505050565b6000806000806060858703121561300457600080fd5b843567ffffffffffffffff81111561301b57600080fd5b61302787828801612d14565b9095509350506020850135915061304060408601612b4c565b905092959194509250565b6000806040838503121561305e57600080fd5b50508035926020909101359150565b60008060006040848603121561308257600080fd5b833567ffffffffffffffff81111561309957600080fd5b6130a586828701612d14565b909790965060209590950135949350505050565b600080600080600060a086880312156130d157600080fd5b6130da86612b4c565b94506130e860208701612b4c565b935060408601359250606086013567ffffffffffffffff8082111561310c57600080fd5b61311889838a01612c41565b9350608088013591508082111561312e57600080fd5b5061313b88828901612c41565b9150509295509295909350565b6000806040838503121561315b57600080fd5b823567ffffffffffffffff8082111561317357600080fd5b612ce786838701612f4b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561278c5761278c61317f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808202811582820484141761278c5761278c61317f565b604081526000612b186040830185612ef1565b8181038181111561278c5761278c61317f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212208b5ead1c3459024e0298de68a5894ce5dc1f53598e590c486cbda8946448061d64736f6c63430008170033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.