Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 4 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19300146 | 267 days ago | Contract Creation | 0 ETH | |||
19300069 | 267 days ago | Contract Creation | 0 ETH | |||
19299714 | 267 days ago | Contract Creation | 0 ETH | |||
19299714 | 267 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
FiftyOneFiftyDeployer
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; import "./FiftyOneFiftyS.sol"; import "./FiftyOneFiftyDashboard.sol"; import "./FiftyOneFiftysUpgrade.sol"; import "./FiftyOneFiftySwap.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /** * @notice Deploys a new FiftyOneFifty environment */ contract FiftyOneFiftyDeployer is Ownable { // --- Contracts --- FiftyOneFiftyDashboard public dashboard; FiftyOneFiftyS public token; FiftyOneFiftysUpgrade public upgrade; FiftyOneFiftySwap public swap; constructor(address _tokenFeeWallet, address _weth) { uint256 initialSupply = 51000000000000000000000000; // Deploying FiftyOneFiftyS ERC20 Token token = new FiftyOneFiftyS( "5150S", "FIFTY", initialSupply, _tokenFeeWallet ); token.setFeeValues(4, 1); token.transfer(msg.sender, initialSupply); token.transferOwnership(msg.sender); // Deploying Dashboard dashboard = new FiftyOneFiftyDashboard(address(token), _weth); dashboard.rolesManager().grantRole( dashboard.rolesManager().DEFAULT_ADMIN_ROLE(), msg.sender ); } function deployUpgrade(address _oldToken) external onlyOwner { // Deploying Upgrade system upgrade = new FiftyOneFiftysUpgrade(IERC20(_oldToken), token); upgrade.transferOwnership(msg.sender); } function deploySwap( ISwapRouter _swapRouter, address _weth, IUniswapV3Pool _uniswapPool ) external onlyOwner { swap = new FiftyOneFiftySwap( _swapRouter, _weth, address(token), _uniswapPool, 500 ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return ERC1155Supply.totalSupply(id) > 0; } /** * @dev See {ERC1155-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @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. * * ``` * 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 of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @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._indexes[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 read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 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 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[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._indexes[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: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.4.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (0 - denominator) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { require((z = uint160(y)) == y); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { require((z = int128(y)) == y); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { require(y < 2**255); z = int256(y); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {SafeCast} from './SafeCast.sol'; import {FullMath} from './FullMath.sol'; import {UnsafeMath} from './UnsafeMath.sol'; import {FixedPoint96} from './FixedPoint96.sol'; /// @title Functions based on Q64.96 sqrt price and liquidity /// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas library SqrtPriceMath { using SafeCast for uint256; /// @notice Gets the next sqrt price given a delta of token0 /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the /// price less in order to not send too much output. /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96), /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount). /// @param sqrtPX96 The starting price, i.e. before accounting for the token0 delta /// @param liquidity The amount of usable liquidity /// @param amount How much of token0 to add or remove from virtual reserves /// @param add Whether to add or remove the amount of token0 /// @return The price after adding or removing amount, depending on add function getNextSqrtPriceFromAmount0RoundingUp( uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add ) internal pure returns (uint160) { // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price if (amount == 0) return sqrtPX96; uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; if (add) { unchecked { uint256 product; if ((product = amount * sqrtPX96) / amount == sqrtPX96) { uint256 denominator = numerator1 + product; if (denominator >= numerator1) // always fits in 160 bits return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator)); } } // denominator is checked for overflow return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount)); } else { unchecked { uint256 product; // if the product overflows, we know the denominator underflows // in addition, we must check that the denominator does not underflow require((product = amount * sqrtPX96) / amount == sqrtPX96 && numerator1 > product); uint256 denominator = numerator1 - product; return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160(); } } } /// @notice Gets the next sqrt price given a delta of token1 /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the /// price less in order to not send too much output. /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity /// @param sqrtPX96 The starting price, i.e., before accounting for the token1 delta /// @param liquidity The amount of usable liquidity /// @param amount How much of token1 to add, or remove, from virtual reserves /// @param add Whether to add, or remove, the amount of token1 /// @return The price after adding or removing `amount` function getNextSqrtPriceFromAmount1RoundingDown( uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add ) internal pure returns (uint160) { // if we're adding (subtracting), rounding down requires rounding the quotient down (up) // in both cases, avoid a mulDiv for most inputs if (add) { uint256 quotient = ( amount <= type(uint160).max ? (amount << FixedPoint96.RESOLUTION) / liquidity : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity) ); return (uint256(sqrtPX96) + quotient).toUint160(); } else { uint256 quotient = ( amount <= type(uint160).max ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity) : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity) ); require(sqrtPX96 > quotient); // always fits 160 bits unchecked { return uint160(sqrtPX96 - quotient); } } } /// @notice Gets the next sqrt price given an input amount of token0 or token1 /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount /// @param liquidity The amount of usable liquidity /// @param amountIn How much of token0, or token1, is being swapped in /// @param zeroForOne Whether the amount in is token0 or token1 /// @return sqrtQX96 The price after adding the input amount to token0 or token1 function getNextSqrtPriceFromInput( uint160 sqrtPX96, uint128 liquidity, uint256 amountIn, bool zeroForOne ) internal pure returns (uint160 sqrtQX96) { require(sqrtPX96 > 0); require(liquidity > 0); // round to make sure that we don't pass the target price return zeroForOne ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true); } /// @notice Gets the next sqrt price given an output amount of token0 or token1 /// @dev Throws if price or liquidity are 0 or the next price is out of bounds /// @param sqrtPX96 The starting price before accounting for the output amount /// @param liquidity The amount of usable liquidity /// @param amountOut How much of token0, or token1, is being swapped out /// @param zeroForOne Whether the amount out is token0 or token1 /// @return sqrtQX96 The price after removing the output amount of token0 or token1 function getNextSqrtPriceFromOutput( uint160 sqrtPX96, uint128 liquidity, uint256 amountOut, bool zeroForOne ) internal pure returns (uint160 sqrtQX96) { require(sqrtPX96 > 0); require(liquidity > 0); // round to make sure that we pass the target price return zeroForOne ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false); } /// @notice Gets the amount0 delta between two prices /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower)) /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up or down /// @return amount0 Amount of token0 required to cover a position of size liquidity between the two passed prices function getAmount0Delta( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity, bool roundUp ) internal pure returns (uint256 amount0) { unchecked { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; uint256 numerator2 = sqrtRatioBX96 - sqrtRatioAX96; require(sqrtRatioAX96 > 0); return roundUp ? UnsafeMath.divRoundingUp( FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), sqrtRatioAX96 ) : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; } } /// @notice Gets the amount1 delta between two prices /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower)) /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up, or down /// @return amount1 Amount of token1 required to cover a position of size liquidity between the two passed prices function getAmount1Delta( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity, bool roundUp ) internal pure returns (uint256 amount1) { unchecked { if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); return roundUp ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96) : FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96); } } /// @notice Helper that gets signed token0 delta /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The change in liquidity for which to compute the amount0 delta /// @return amount0 Amount of token0 corresponding to the passed liquidityDelta between the two prices function getAmount0Delta( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, int128 liquidity ) internal pure returns (int256 amount0) { unchecked { return liquidity < 0 ? -getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256() : getAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256(); } } /// @notice Helper that gets signed token1 delta /// @param sqrtRatioAX96 A sqrt price /// @param sqrtRatioBX96 Another sqrt price /// @param liquidity The change in liquidity for which to compute the amount1 delta /// @return amount1 Amount of token1 corresponding to the passed liquidityDelta between the two prices function getAmount1Delta( uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, int128 liquidity ) internal pure returns (int256 amount1) { unchecked { return liquidity < 0 ? -getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(-liquidity), false).toInt256() : getAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, uint128(liquidity), true).toInt256(); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Math functions that do not check inputs or outputs /// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks library UnsafeMath { /// @notice Returns ceil(x / y) /// @dev division by 0 has unspecified behavior, and must be checked externally /// @param x The dividend /// @param y The divisor /// @return z The quotient, ceil(x / y) function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := add(div(x, y), gt(mod(x, y), 0)) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; library TransferHelper { /// @notice Transfers tokens from the targeted address to the given destination /// @notice Errors with 'STF' if transfer fails /// @param token The contract address of the token to be transferred /// @param from The originating address from which the tokens will be transferred /// @param to The destination address of the transfer /// @param value The amount to be transferred function safeTransferFrom( address token, address from, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value) ); require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); } /// @notice Transfers tokens from msg.sender to a recipient /// @dev Errors with ST if transfer fails /// @param token The contract address of the token which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer function safeTransfer( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); } /// @notice Approves the stipulated contract to spend the given allowance in the given token /// @dev Errors with 'SA' if transfer fails /// @param token The contract address of the token to be approved /// @param to The target of the approval /// @param value The amount of the given token the target will be allowed to spend function safeApprove( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); } /// @notice Transfers ETH to the recipient address /// @dev Fails with `STE` /// @param to The destination of the transfer /// @param value The value to be transferred function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'STE'); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "./RolesManager.sol"; import "@uniswap/v3-core/contracts/libraries/FullMath.sol"; import "./IUniswapV3Pool.sol"; // ______ _ __ _ ____ ______ _ __ _ _ // | ____(_)/ _| | / __ \ | ____(_)/ _| | | | // | |__ _| |_| |_ _ _| | | |_ __ ___| |__ _| |_| |_ _ _ ___ ___ | | // | __| | | _| __| | | | | | | '_ \ / _ \ __| | | _| __| | | | / __|/ _ \| | // | | | | | | |_| |_| | |__| | | | | __/ | | | | | |_| |_| |_\__ \ (_) | | // |_| |_|_| \__|\__, |\____/|_| |_|\___|_| |_|_| \__|\__, (_)___/\___/|_| // __/ | __/ | // |___/ |___/ interface IFityOneFifty is IERC1155 { function addId( uint256 _mintPrice, uint256 _maxSupply, bool _revealed, uint256 _revealDate, string memory _cid ) external; function setRevealed(bool _revealed) external; function setPaused(bool _paused) external; function setERC20Address(address _tokenAddress) external; function setUriSuffix(string memory _newUriSuffix) external; function uri(uint256 _id) external; function _getIdIndex(uint256 _id) external; function getIdsArray() external; function setMintPrice(uint256 _id, uint256 _mintPrice) external; function setMaxSupply(uint256 _id, uint256 _maxSupply) external; function setNftReveal(uint256 _id, bool _revealed) external; function setNftRevealDate(uint256 _id, uint256 _revealDate) external; function setIdCid(uint256 _id, string memory _newCid) external; function mintForAddress( address _recipientAccount, uint256 _id, uint256 _mintAmount ) external; function mint(uint256 _id, uint256 _mintAmount) external; function ownerMintForAddress( uint256 _mintAmount, address _receiver, uint256 _id ) external; function multiCall(bytes[] calldata data) external; function withdrawBalance() external; } contract FiftyOneFifty is ERC1155Supply, RolesManagerConsumer, ReentrancyGuard { event NewIdCreated( uint256 indexed id, uint256 indexed mintPrice, uint256 indexed maxSupply, bool revealed, uint256 revealDate, string cid ); IERC20 public tokenAddress; string public name; string public symbol; address public weth; bytes4 public constant IFIFTYONEFIFTY_INTERFACE_ID = type(IFityOneFifty).interfaceId; bytes32 public constant EDITOR_ROLE = keccak256("EDITOR_ROLE"); string public baseUri = "ipfs://"; string public uriSuffix = "/metadata.json"; bool public revealed = false; bool public paused = true; IUniswapV3Pool public uniswapV3Pool; struct IdInfo { uint256 id; uint256 mintPrice; uint256 maxSupply; bool revealed; uint256 revealDate; string cid; uint256 lastMintDate; } IdInfo[] public idsInfo; /** * @notice Contract constructor * @param _tokenName Token name * @param _tokenName Token symbol */ constructor( string memory _tokenName, string memory _tokenSymbol, string memory _uri, address _tokenAddress, address _rolesManager, address _weth ) ERC1155(_uri) RolesManagerConsumer(_rolesManager) { name = _tokenName; symbol = _tokenSymbol; tokenAddress = IERC20(_tokenAddress); weth = _weth; } modifier idExists(uint256 _id) { bool idFound = false; for (uint256 i = 0; i < idsInfo.length; i++) { if (idsInfo[i].id == _id) idFound = true; } require(idFound, "Id not found"); _; } /** * @dev Checks if caller can mint */ modifier canMint(uint256 _mintAmount, uint256 _id) { require( totalSupply(_id) + _mintAmount <= idsInfo[_getIdIndex(_id)].maxSupply, "Max supply exceed!" ); _; } modifier active() { require(!paused, "Contract is paused."); _; } function addId( uint256 _mintPrice, uint256 _maxSupply, bool _revealed, uint256 _revealDate, string memory _cid ) public requireEditor(_msgSender()) { IdInfo memory newId = IdInfo( idsInfo.length, _mintPrice, _maxSupply, _revealed, _revealDate, _cid, 0 ); idsInfo.push(newId); emit NewIdCreated( idsInfo.length, _mintPrice, _maxSupply, _revealed, _revealDate, _cid ); } /** * @notice Reveals (or unreveals) the collection * @param _revealed New revealed value to be set. True if revealed, false otherwise */ function setRevealed(bool _revealed) public requireAdmin(_msgSender()) { revealed = _revealed; } /** * @notice Change paused state * @param _paused Paused state */ function setPaused(bool _paused) public requireAdmin(_msgSender()) { paused = _paused; } function setERC20Address( address _tokenAddress ) public requireAdmin(_msgSender()) { tokenAddress = IERC20(_tokenAddress); } function setBaseUri( string memory _newBaseUri ) public requireAdmin(_msgSender()) { baseUri = _newBaseUri; } function setUriSuffix( string memory _newUriSuffix ) public requireAdmin(_msgSender()) { uriSuffix = _newUriSuffix; } function uri(uint256 _id) public view override returns (string memory) { string memory newUri; for (uint256 i = 0; i < idsInfo.length; ++i) { if (idsInfo[i].id == _id) { newUri = string( abi.encodePacked(baseUri, idsInfo[i].cid, uriSuffix) ); } } return newUri; } function _getIdIndex(uint256 _id) internal view returns (uint256 index) { for (uint256 i = 0; i < idsInfo.length; ++i) { if (idsInfo[i].id == _id) return i; } require(false, "Id not found"); } function getIdsArray() public view returns (uint256[] memory) { uint256[] memory ids = new uint256[](idsInfo.length); for (uint256 i = 0; i < idsInfo.length; i++) { ids[i] = idsInfo[i].id; } return ids; } function setUniswapV3PoolAddress( address _uniswapV3Pool ) public requireAdmin(_msgSender()) { uniswapV3Pool = IUniswapV3Pool(_uniswapV3Pool); } function getPoolTokenPrice() public view returns (uint256) { (uint160 sqrtPriceX96, , , , , , ) = uniswapV3Pool.slot0(); uint256 numerator1 = uint256(sqrtPriceX96) * uint256(sqrtPriceX96); uint256 numerator2 = 10 ** 18; uint256 ratio = FullMath.mulDiv(numerator1, numerator2, 1 << 192); return ratio; } /** * @notice Allows owner to set a new mint price */ function setMintPrice( uint256 _id, uint256 _mintPrice ) public requireEditor(_msgSender()) { idsInfo[_getIdIndex(_id)].mintPrice = _mintPrice; } /** * @notice Returns the mint price for a given id. The price is expressed in terms of token, not Ether. */ function getMintPrice(uint256 _id) public view returns (uint256) { if (address(tokenAddress) > weth) { return (idsInfo[_getIdIndex(_id)].mintPrice * getPoolTokenPrice()) / 1e18; } else { return ((idsInfo[_getIdIndex(_id)].mintPrice * 1e18) / getPoolTokenPrice()); } } function setMaxSupply( uint256 _id, uint256 _maxSupply ) public requireEditor(_msgSender()) { require( _maxSupply > totalSupply(_id), "Max supply can not be less than total supply." ); idsInfo[_getIdIndex(_id)].maxSupply = _maxSupply; } function setNftReveal( uint256 _id, bool _revealed ) public requireEditor(_msgSender()) { idsInfo[_getIdIndex(_id)].revealed = _revealed; } function setNftRevealDate( uint256 _id, uint256 _revealDate ) public requireEditor(_msgSender()) { idsInfo[_getIdIndex(_id)].revealDate = _revealDate; } function setIdCid( uint256 _id, string memory _newCid ) public requireEditor(_msgSender()) { idsInfo[_getIdIndex(_id)].cid = _newCid; } function mintForAddress( address _recipientAccount, uint256 _id, uint256 _mintAmount ) public idExists(_id) canMint(_mintAmount, _id) active nonReentrant { for (uint256 i = 0; i < idsInfo.length; i++) { if (idsInfo[i].id == _id) { uint256 tokenMintPrice = getMintPrice(_id); require( tokenAddress.balanceOf(_msgSender()) >= tokenMintPrice * _mintAmount, "Insufficient funds!!!" ); if (idsInfo[i].maxSupply != 0) { require( totalSupply(_id) + _mintAmount <= idsInfo[i].maxSupply, "Max supply reached" ); } require(idsInfo[i].revealed, "NFT not released yet"); tokenAddress.transferFrom( _msgSender(), address(this), tokenMintPrice * _mintAmount ); idsInfo[i].lastMintDate = block.timestamp; _mint(_recipientAccount, _id, _mintAmount, ""); } } } function mint(uint256 _id, uint256 _mintAmount) public { mintForAddress(_msgSender(), _id, _mintAmount); } /** * @notice Mints item for another address. (Reserved to contract owner) */ function ownerMintForAddress( uint256 _mintAmount, address _receiver, uint256 _id ) public virtual canMint(_mintAmount, _id) requireAdmin(_msgSender()) { uint256 idIndex = _getIdIndex(_id); require( totalSupply(_id) + _mintAmount <= idsInfo[idIndex].maxSupply, "Max supply exceed!" ); idsInfo[idIndex].lastMintDate = block.timestamp; _mint(_receiver, _id, _mintAmount, ""); } function multiCall( bytes[] calldata data ) external returns (bytes[] memory) { bytes[] memory results = new bytes[](data.length); for (uint i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall( data[i] ); require(success, "call failed"); results[i] = result; } return results; } /** * @notice Withdraws contract balance to onwer account */ function withdrawBalance() public requireAdmin(_msgSender()) { tokenAddress.transfer( _msgSender(), tokenAddress.balanceOf(address(this)) ); } function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC1155) returns (bool) { return interfaceId == type(IFityOneFifty).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "./FiftyOneFifty.sol"; import "./RolesManager.sol"; contract FiftyOneFiftyDashboard is RolesManagerConsumer { FiftyOneFifty[] public collectionsAddresses; address public erc20Address; address public weth; address public poolAddress; event NewCollectionDeployed(address collectionAddress); constructor( address _erc20Address, address _weth ) RolesManagerConsumer(address(0x0)) { erc20Address = _erc20Address; weth = _weth; } function deployNewCollection( string memory _collectionName, string memory _symbol ) public requireAdmin(msg.sender) { require(poolAddress != address(0), "Pool address not set"); FiftyOneFifty collection = new FiftyOneFifty( _collectionName, _symbol, "", erc20Address, address(rolesManager), weth ); collection.setUniswapV3PoolAddress(poolAddress); addContract(collection); // Emitting event emit NewCollectionDeployed(address(collection)); } function addContract( FiftyOneFifty _contractAddress ) public requireAdmin(msg.sender) { collectionsAddresses.push(_contractAddress); } function setPoolAddress( address _poolAddress ) public requireAdmin(msg.sender) { poolAddress = _poolAddress; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract FiftyOneFiftyS is ERC20, Ownable { address public uniswapPoolAddress = address(0); uint256 public taxFeeToOwner = 0; uint256 public taxFeeToPool = 0; address feeWallet; address public upgradeContractAddress = address(0); constructor( string memory _name, string memory _symbol, uint256 _initialSupply, address _feeWallet ) ERC20(_name, _symbol) { _mint(msg.sender, _initialSupply); feeWallet = _feeWallet; } function setUniswapAddresses(address _address) public onlyOwner { uniswapPoolAddress = _address; } function setUpgradeContractAddress(address _address) public onlyOwner { upgradeContractAddress = _address; } function setFeeValues( uint256 _taxFeeToOwner, uint256 _taxFeeToPool ) public onlyOwner { taxFeeToOwner = _taxFeeToOwner; taxFeeToPool = _taxFeeToPool; } function getFeeValue() public view returns (uint256, uint256) { return (taxFeeToOwner, taxFeeToPool); } function setFeeWalletAddress(address _walletAddress) public onlyOwner { feeWallet = _walletAddress; } function _transfer( address _from, address _to, uint256 _amount ) internal override { uint256 finalOwnerFee = taxFeeToOwner; uint256 finalPoolFee = taxFeeToPool; if ( _from == owner() || _to == owner() || _to == uniswapPoolAddress || _from == upgradeContractAddress ) { finalOwnerFee = 0; finalPoolFee = 0; } uint256 ownerFeeAmount = (_amount * finalOwnerFee) / 100; uint256 poolFeeAmount = (_amount * finalPoolFee) / 100; uint256 amountAfterTaxes = (_amount - ownerFeeAmount) - poolFeeAmount; super._transfer(_from, _to, amountAfterTaxes); if (ownerFeeAmount > 0) { super._transfer(_from, feeWallet, ownerFeeAmount); } if (poolFeeAmount > 0) { _burn(_from, poolFeeAmount); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract FiftyOneFiftysUpgrade is Ownable { using SafeMath for uint256; mapping(address => bool) public hasAlreadyUpgradeed; IERC20 private oldToken; IERC20 private newToken; uint256 public creationTime; constructor(IERC20 _oldToken, IERC20 _newToken) { oldToken = _oldToken; newToken = _newToken; setCreationTime(); } function setCreationTime() internal { creationTime = block.timestamp; } function getUpgradeableAmount() public view returns (uint256) { //gets the user's balance of the old token contract uint256 oldTokenOwned = oldToken.balanceOf(msg.sender); //calculates the amount of new tokens that can be upgradeed uint256 upgradeableAmount = SafeMath.div( SafeMath.mul(oldTokenOwned, 4), 1000 ); return upgradeableAmount; } function upgradeTokens() public { //redemption time limit check (after two weeks from the deploy the upgrade will not be available) require( block.timestamp < creationTime + 2 weeks, "Tokens upgrade is not available anymore" ); //checks the amount of upgradeable token uint256 tokenToSend = getUpgradeableAmount(); require(tokenToSend > 0, "No upgradeable tokens"); // Transfer the old token to the contract require( oldToken.transferFrom( msg.sender, address(this), oldToken.balanceOf(msg.sender) ), "Old token transfer failed" ); //transfers the tokens to the user require( newToken.transfer(msg.sender, tokenToSend), "Token transfer failed" ); hasAlreadyUpgradeed[msg.sender] = true; } function withdrawToken(address _token) public onlyOwner { IERC20 token = IERC20(_token); token.transfer(owner(), token.balanceOf(address(this))); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.14; pragma abicoder v2; import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@uniswap/v3-core/contracts/libraries/SqrtPriceMath.sol"; import "./IUniswapV3Pool.sol"; interface IWETH { function deposit() external payable; } contract FiftyOneFiftySwap is Ownable { ISwapRouter public swapRouter; IUniswapV3Pool public uniswapPool; address public token0; address public token1; uint24 public poolFee; uint16 public transferFee = 5; uint16 public slippage = 5; constructor( ISwapRouter _swapRouter, address _weth, address _fofs, IUniswapV3Pool _uniswapPool, uint24 _poolFee ) { swapRouter = _swapRouter; token0 = _weth; token1 = _fofs; uniswapPool = _uniswapPool; poolFee = _poolFee; } function setSwapRouterAddress(address _swapRouterAddress) public onlyOwner { swapRouter = ISwapRouter(_swapRouterAddress); } function setTokensAddress( address _token0, address _token1 ) public onlyOwner { token0 = _token0; token1 = _token1; } function setUniswapPoolAddress( address _uniswapPoolAddress ) public onlyOwner { uniswapPool = IUniswapV3Pool(_uniswapPoolAddress); } function setPoolFee(uint24 _fee) public onlyOwner { poolFee = _fee; } function setTransferFee(uint16 _fee) public onlyOwner { transferFee = _fee; } function setSlippage(uint16 _slippage) public onlyOwner { slippage = _slippage; } function getSwapEstimatedInputAmount( uint256 amountOut ) public view returns (uint256) { (uint160 sqrtPriceX96, , , , , , ) = uniswapPool.slot0(); uint128 liquidity = uniswapPool.liquidity(); bool tokenOrder; if (token0 < token1) { tokenOrder = false; } else { tokenOrder = true; } amountOut += ((amountOut / 100) * transferFee) + (amountOut / poolFee) + ((amountOut / 1000) * slippage); uint160 nextSqrtPriceX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( sqrtPriceX96, liquidity, amountOut, !tokenOrder ); uint256 estimatedAmountIn; if (!tokenOrder) { estimatedAmountIn = SqrtPriceMath.getAmount0Delta( sqrtPriceX96, nextSqrtPriceX96, liquidity, false ); } else { estimatedAmountIn = SqrtPriceMath.getAmount1Delta( sqrtPriceX96, nextSqrtPriceX96, liquidity, false ); } return estimatedAmountIn; } function getSwapEstimatedOutputAmount( uint256 amountIn ) public view returns (uint256, uint256) { (uint160 sqrtPriceX96, , , , , , ) = uniswapPool.slot0(); uint128 liquidity = uniswapPool.liquidity(); bool tokenOrder; if (token0 < token1) { tokenOrder = false; } else { tokenOrder = true; } uint160 nextSqrtPriceX96 = SqrtPriceMath.getNextSqrtPriceFromInput( sqrtPriceX96, liquidity, amountIn, !tokenOrder ); uint256 estimatedAmountOut; if (tokenOrder) { estimatedAmountOut = SqrtPriceMath.getAmount0Delta( sqrtPriceX96, nextSqrtPriceX96, liquidity, false ); } else { estimatedAmountOut = SqrtPriceMath.getAmount1Delta( sqrtPriceX96, nextSqrtPriceX96, liquidity, false ); } estimatedAmountOut -= (estimatedAmountOut / poolFee); uint amountOutWithTransferFees = estimatedAmountOut - (estimatedAmountOut / 100) * transferFee; return (estimatedAmountOut, amountOutWithTransferFees); } function swapExactInputSingle( uint256 amountIn, uint256 estimatedAmountOut ) external payable returns (uint256 amountOut) { uint256 amountOutMinimum = estimatedAmountOut - ((estimatedAmountOut / 1000) * slippage); IWETH(token0).deposit{value: amountIn}(); TransferHelper.safeApprove(token0, address(swapRouter), amountIn); ISwapRouter.ExactInputSingleParams memory params = ISwapRouter .ExactInputSingleParams({ tokenIn: token0, tokenOut: token1, fee: poolFee, recipient: msg.sender, deadline: block.timestamp, amountIn: amountIn, amountOutMinimum: amountOutMinimum, sqrtPriceLimitX96: 0 }); amountOut = swapRouter.exactInputSingle(params); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.14; interface IUniswapV3Pool { function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function liquidity() external view returns (uint128); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.14; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; /** * @notice Implements a roles manager based on OpenZeppelin's AccessControl lib */ contract RolesManager is AccessControlEnumerable { bytes32 public constant EDITOR_ROLE = keccak256("EDITOR_ROLE"); constructor() { _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); } } /** * @notice Consumer contract for `RolesManager` */ contract RolesManagerConsumer { /// @notice Roles Manager instance RolesManager public rolesManager; constructor(address _rolesManager) { if (address(_rolesManager) == address(0x0)) { rolesManager = new RolesManager(); rolesManager.grantRole( rolesManager.DEFAULT_ADMIN_ROLE(), msg.sender ); } else { rolesManager = RolesManager(_rolesManager); } } modifier requireAdmin(address _account) { require( rolesManager.hasRole(rolesManager.DEFAULT_ADMIN_ROLE(), _account), "ADMIN role is required" ); _; } modifier requireEditor(address _account) { require( rolesManager.hasRole(rolesManager.EDITOR_ROLE(), _account) || rolesManager.hasRole( rolesManager.DEFAULT_ADMIN_ROLE(), _account ), "EDITOR role or higher is required" ); _; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_tokenFeeWallet","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"dashboard","outputs":[{"internalType":"contract FiftyOneFiftyDashboard","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISwapRouter","name":"_swapRouter","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"contract IUniswapV3Pool","name":"_uniswapPool","type":"address"}],"name":"deploySwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oldToken","type":"address"}],"name":"deployUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swap","outputs":[{"internalType":"contract FiftyOneFiftySwap","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract FiftyOneFiftyS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgrade","outputs":[{"internalType":"contract FiftyOneFiftysUpgrade","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516200aa153803806200aa15833981016040819052610031916104a3565b61003a3361041f565b60006a2a2fab8a32d35713000000905080836040516100589061046f565b6080808252600590820181905264353135305360d81b60a083015260c06020830181905282015264464946545960d81b60e082015260408101929092526001600160a01b0316606082015261010001604051809103906000f0801580156100c3573d6000803e3d6000fd5b50600280546001600160a01b0319166001600160a01b039290921691821790556040516352af680760e01b8152600480820152600160248201526352af680790604401600060405180830381600087803b15801561012057600080fd5b505af1158015610134573d6000803e3d6000fd5b505060025460405163a9059cbb60e01b8152336004820152602481018590526001600160a01b03909116925063a9059cbb91506044016020604051808303816000875af1158015610189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101ad91906104dd565b5060025460405163f2fde38b60e01b81523360048201526001600160a01b039091169063f2fde38b90602401600060405180830381600087803b1580156101f357600080fd5b505af1158015610207573d6000803e3d6000fd5b50506002546040516001600160a01b0390911692508491506102289061047d565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801561025b573d6000803e3d6000fd5b50600180546001600160a01b0319166001600160a01b039290921691821790556040805163a3574c5b60e01b8152905163a3574c5b916004808201926020929091908290030181865afa1580156102b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102da9190610506565b6001600160a01b0316632f2ff15d600160009054906101000a90046001600160a01b03166001600160a01b031663a3574c5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561033b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035f9190610506565b6001600160a01b031663a217fddf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561039c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c09190610523565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b1580156103ff57600080fd5b505af1158015610413573d6000803e3d6000fd5b5050505050505061053c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6112ca806200299b83390190565b616db08062003c6583390190565b6001600160a01b03811681146104a057600080fd5b50565b600080604083850312156104b657600080fd5b82516104c18161048b565b60208401519092506104d28161048b565b809150509250929050565b6000602082840312156104ef57600080fd5b815180151581146104ff57600080fd5b9392505050565b60006020828403121561051857600080fd5b81516104ff8161048b565b60006020828403121561053557600080fd5b5051919050565b61244f806200054c6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a2c9409911610066578063a2c94099146100f5578063d55ec69714610108578063e4bfdcdc1461011b578063f2fde38b1461012e578063fc0c546a1461014157600080fd5b8063715018a614610098578063799f99bc146100a25780638119c065146100b55780638da5cb5b146100e4575b600080fd5b6100a0610154565b005b6100a06100b036600461042c565b610168565b6004546100c8906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6000546001600160a01b03166100c8565b6001546100c8906001600160a01b031681565b6003546100c8906001600160a01b031681565b6100a0610129366004610477565b61020e565b6100a061013c366004610477565b6102d5565b6002546100c8906001600160a01b031681565b61015c610353565b61016660006103ad565b565b610170610353565b8282600260009054906101000a90046001600160a01b0316836101f4604051610198906103fd565b6001600160a01b03958616815293851660208501529184166040840152909216606082015262ffffff909116608082015260a001604051809103906000f0801580156101e8573d6000803e3d6000fd5b50600480546001600160a01b0319166001600160a01b0392909216919091179055505050565b610216610353565b60025460405182916001600160a01b0316906102319061040a565b6001600160a01b03928316815291166020820152604001604051809103906000f080158015610264573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b0392909216918217905560405163f2fde38b60e01b815233600482015263f2fde38b90602401600060405180830381600087803b1580156102ba57600080fd5b505af11580156102ce573d6000803e3d6000fd5b5050505050565b6102dd610353565b6001600160a01b0381166103475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610350816103ad565b50565b6000546001600160a01b031633146101665760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161033e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6116558061049c83390190565b61092980611af183390190565b6001600160a01b038116811461035057600080fd5b60008060006060848603121561044157600080fd5b833561044c81610417565b9250602084013561045c81610417565b9150604084013561046c81610417565b809150509250925092565b60006020828403121561048957600080fd5b813561049481610417565b939250505056fe60806040526004805463ffffffff60b81b19166205000560b81b1790553480156200002957600080fd5b5060405162001655380380620016558339810160408190526200004c916200012e565b6200005733620000c5565b600180546001600160a01b039687166001600160a01b03199182161790915560038054958716958216959095179094556004805460028054948816949096169390931790945562ffffff16600160a01b026001600160b81b03199091169190931617919091179055620001b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200012b57600080fd5b50565b600080600080600060a086880312156200014757600080fd5b8551620001548162000115565b6020870151909550620001678162000115565b60408701519094506200017a8162000115565b60608701519093506200018d8162000115565b608087015190925062ffffff81168114620001a757600080fd5b809150509295509295909350565b61149080620001c56000396000f3fe6080604052600436106101145760003560e01c80638da5cb5b116100a0578063c31c9c0711610064578063c31c9c071461031a578063d21220a71461033a578063deae729e1461035a578063f2fde38b1461037a578063f41167921461039a57600080fd5b80638da5cb5b1461027a578063ab37fbb714610298578063acb2ad6f146102b8578063b44cb06f146102da578063bdd3d825146102fa57600080fd5b80635249961b116100e75780635249961b146101e357806359966cfd14610205578063715018a61461022557806373dd250c1461023a57806383ce916a1461025a57600080fd5b8063089fe6aa146101195780630dfe1681146101555780633e032a3b1461018d57806349cdeeb9146101c2575b600080fd5b34801561012557600080fd5b5060045461013c90600160a01b900462ffffff1681565b60405162ffffff90911681526020015b60405180910390f35b34801561016157600080fd5b50600354610175906001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b34801561019957600080fd5b506004546101af90600160c81b900461ffff1681565b60405161ffff909116815260200161014c565b6101d56101d03660046110fd565b6103cf565b60405190815260200161014c565b3480156101ef57600080fd5b506102036101fe366004611134565b610556565b005b34801561021157600080fd5b50610203610220366004611161565b610580565b34801561023157600080fd5b506102036105aa565b34801561024657600080fd5b5061020361025536600461117e565b6105be565b34801561026657600080fd5b506101d56102753660046111a3565b6105ea565b34801561028657600080fd5b506000546001600160a01b0316610175565b3480156102a457600080fd5b506102036102b3366004611161565b6107d6565b3480156102c457600080fd5b506004546101af90600160b81b900461ffff1681565b3480156102e657600080fd5b506102036102f53660046111bc565b610800565b34801561030657600080fd5b50600254610175906001600160a01b031681565b34801561032657600080fd5b50600154610175906001600160a01b031681565b34801561034657600080fd5b50600454610175906001600160a01b031681565b34801561036657600080fd5b50610203610375366004611134565b610836565b34801561038657600080fd5b50610203610395366004611134565b610860565b3480156103a657600080fd5b506103ba6103b53660046111a3565b6108de565b6040805192835260208301919091520161014c565b6004546000908190600160c81b900461ffff166103ee6103e885611221565b6103f89190611243565b6104029084611262565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561045457600080fd5b505af1158015610468573d6000803e3d6000fd5b505060035460015461048b94506001600160a01b03918216935016905086610aa9565b60408051610100810182526003546001600160a01b039081168252600480548083166020850152600160a01b900462ffffff168385015233606084015242608084015260a0830188905260c08301859052600060e0840152600154935163414bf38960e01b815292939091169163414bf3899161050a91859101611279565b6020604051808303816000875af1158015610529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054d91906112f6565b95945050505050565b61055e610ba9565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b610588610ba9565b6004805461ffff909216600160b81b0261ffff60b81b19909216919091179055565b6105b2610ba9565b6105bc6000610c03565b565b6105c6610ba9565b6004805462ffffff909216600160a01b0262ffffff60a01b19909216919091179055565b600080600260009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610664919061131f565b50505050505090506000600260009054906101000a90046001600160a01b03166001600160a01b0316631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e591906113c3565b6004546003549192506000916001600160a01b039182169116101561070c57506000610710565b5060015b600454600160c81b900461ffff1661072a6103e887611221565b6107349190611243565b60045461074d90600160a01b900462ffffff1687611221565b600454600160b81b900461ffff16610766606489611221565b6107709190611243565b61077a91906113ec565b61078491906113ec565b61078e90866113ec565b9450600061079f8484888515610c53565b90506000826107bc576107b58583866000610caf565b90506107cc565b6107c98583866000610d66565b90505b9695505050505050565b6107de610ba9565b6004805461ffff909216600160c81b0261ffff60c81b19909216919091179055565b610808610ba9565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b61083e610ba9565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610868610ba9565b6001600160a01b0381166108d25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6108db81610c03565b50565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095a919061131f565b50505050505090506000600260009054906101000a90046001600160a01b03166001600160a01b0316631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109db91906113c3565b6004546003549192506000916001600160a01b0391821691161015610a0257506000610a06565b5060015b6000610a158484898515610dd1565b905060008215610a3357610a2c8583866000610caf565b9050610a43565b610a408583866000610d66565b90505b600454610a5c90600160a01b900462ffffff1682611221565b610a669082611262565b600454909150600090600160b81b900461ffff16610a85606484611221565b610a8f9190611243565b610a999083611262565b9199919850909650505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151600092839290871691610b059190611404565b6000604051808303816000865af19150503d8060008114610b42576040519150601f19603f3d011682016040523d82523d6000602084013e610b47565b606091505b5091509150818015610b71575080511580610b71575080806020019051810190610b71919061143f565b610ba25760405162461bcd60e51b8152602060048201526002602482015261534160f01b60448201526064016108c9565b5050505050565b6000546001600160a01b031633146105bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080856001600160a01b031611610c6a57600080fd5b6000846001600160801b031611610c8057600080fd5b81610c9757610c928585856000610e19565b610ca4565b610ca48585856000610f16565b90505b949350505050565b6000836001600160a01b0316856001600160a01b03161115610ccf579293925b600160601b600160e01b03606084901b166001600160a01b038686038116908716610cf957600080fd5b83610d2f57866001600160a01b0316610d1c8383896001600160a01b0316610fef565b81610d2957610d296111f5565b04610d5b565b610d5b610d468383896001600160a01b03166110a2565b886001600160a01b0316808204910615150190565b979650505050505050565b6000836001600160a01b0316856001600160a01b03161115610d86579293925b81610dae57610c92836001600160801b03168686036001600160a01b0316600160601b610fef565b610ca4836001600160801b03168686036001600160a01b0316600160601b6110a2565b600080856001600160a01b031611610de857600080fd5b6000846001600160801b031611610dfe57600080fd5b81610e1057610c928585856001610f16565b610ca485858560015b600082600003610e2a575083610ca7565b600160601b600160e01b03606085901b168215610ec4576001600160a01b03861684810290858281610e5e57610e5e6111f5565b0403610e8e57818101828110610e8c57610e8283896001600160a01b0316836110a2565b9350505050610ca7565b505b50610ebc8185610ea76001600160a01b038a1683611221565b610eb191906113ec565b808204910615150190565b915050610ca7565b6001600160a01b03861684810290858281610ee157610ee16111f5565b04148015610eee57508082115b610ef757600080fd5b808203610e82610f11846001600160a01b038b16846110a2565b6110e2565b60008115610f7b5760006001600160a01b03841115610f4c57610f4784600160601b876001600160801b0316610fef565b610f63565b610f636001600160801b038616606086901b611221565b9050610ebc610f11826001600160a01b0389166113ec565b60006001600160a01b03841115610fa957610fa484600160601b876001600160801b03166110a2565b610fc6565b610fc6606085901b6001600160801b038716808204910615150190565b905080866001600160a01b031611610fdd57600080fd5b6001600160a01b038616039050610ca7565b6000808060001985870985870292508281108382030391505080600003611028576000841161101d57600080fd5b50829004905061109b565b80841161103457600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60006110af848484610fef565b9050600082806110c1576110c16111f5565b848609111561109b5760001981106110d857600080fd5b6001019392505050565b806001600160a01b03811681146110f857600080fd5b919050565b6000806040838503121561111057600080fd5b50508035926020909101359150565b6001600160a01b03811681146108db57600080fd5b60006020828403121561114657600080fd5b813561109b8161111f565b61ffff811681146108db57600080fd5b60006020828403121561117357600080fd5b813561109b81611151565b60006020828403121561119057600080fd5b813562ffffff8116811461109b57600080fd5b6000602082840312156111b557600080fd5b5035919050565b600080604083850312156111cf57600080fd5b82356111da8161111f565b915060208301356111ea8161111f565b809150509250929050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261123e57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561125d5761125d61120b565b500290565b6000828210156112745761127461120b565b500390565b60006101008201905060018060a01b0380845116835280602085015116602084015262ffffff6040850151166040840152806060850151166060840152506080830151608083015260a083015160a083015260c083015160c083015260e08301516112ef60e08401826001600160a01b03169052565b5092915050565b60006020828403121561130857600080fd5b5051919050565b805180151581146110f857600080fd5b600080600080600080600060e0888a03121561133a57600080fd5b87516113458161111f565b8097505060208801518060020b811461135d57600080fd5b604089015190965061136e81611151565b606089015190955061137f81611151565b608089015190945061139081611151565b60a089015190935060ff811681146113a757600080fd5b91506113b560c0890161130f565b905092959891949750929550565b6000602082840312156113d557600080fd5b81516001600160801b038116811461109b57600080fd5b600082198211156113ff576113ff61120b565b500190565b6000825160005b81811015611425576020818601810151858301520161140b565b81811115611434576000828501525b509190910192915050565b60006020828403121561145157600080fd5b61109b8261130f56fea264697066735822122007790787babb7848758c81e19044e8a682e61e8edf809970e0eb58b35c34435a64736f6c634300080e0033608060405234801561001057600080fd5b5060405161092938038061092983398101604081905261002f916100e4565b61003833610078565b600280546001600160a01b038085166001600160a01b031992831617909255600380549284169290911691909117905561007142600455565b5050610117565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146100df57600080fd5b919050565b600080604083850312156100f757600080fd5b610100836100c8565b915061010e602084016100c8565b90509250929050565b610803806101266000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100cd578063b9166076146100e8578063d8270dce1461011b578063f2fde38b1461012457600080fd5b80633d0b1e2c1461008d5780636febc51814610097578063715018a6146100b257806389476069146100ba575b600080fd5b610095610137565b005b61009f610413565b6040519081526020015b60405180910390f35b6100956104a5565b6100956100c83660046106fa565b6104b9565b6000546040516001600160a01b0390911681526020016100a9565b61010b6100f63660046106fa565b60016020526000908152604090205460ff1681565b60405190151581526020016100a9565b61009f60045481565b6100956101323660046106fa565b6105bf565b6004546101479062127500610739565b42106101aa5760405162461bcd60e51b815260206004820152602760248201527f546f6b656e732075706772616465206973206e6f7420617661696c61626c6520604482015266616e796d6f726560c81b60648201526084015b60405180910390fd5b60006101b4610413565b9050600081116101fe5760405162461bcd60e51b81526020600482015260156024820152744e6f207570677261646561626c6520746f6b656e7360581b60448201526064016101a1565b6002546040516370a0823160e01b815233600482018190526001600160a01b03909216916323b872dd91309084906370a0823190602401602060405180830381865afa158015610252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102769190610751565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156102ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ee919061076a565b61033a5760405162461bcd60e51b815260206004820152601960248201527f4f6c6420746f6b656e207472616e73666572206661696c65640000000000000060448201526064016101a1565b60035460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af115801561038b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103af919061076a565b6103f35760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b60448201526064016101a1565b50336000908152600160208190526040909120805460ff19169091179055565b6002546040516370a0823160e01b815233600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610460573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104849190610751565b9050600061049e610496836004610638565b6103e8610644565b9392505050565b6104ad610650565b6104b760006106aa565b565b6104c1610650565b806001600160a01b03811663a9059cbb6104e36000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b9190610751565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ba919061076a565b505050565b6105c7610650565b6001600160a01b03811661062c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016101a1565b610635816106aa565b50565b600061049e828461078c565b600061049e82846107ab565b6000546001600160a01b031633146104b75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561070c57600080fd5b81356001600160a01b038116811461049e57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561074c5761074c610723565b500190565b60006020828403121561076357600080fd5b5051919050565b60006020828403121561077c57600080fd5b8151801515811461049e57600080fd5b60008160001904831182151516156107a6576107a6610723565b500290565b6000826107c857634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220ecd9efbd613b33b8e7f8a6f5ee8c093e0d7ca96f4d7335906eaaaaa316099be464736f6c634300080e0033a2646970667358221220247e53c2e975dfad108835fd9d9c839821da9065e554ab88b6face52b2775e3f64736f6c634300080e00336080604052600680546001600160a01b031990811690915560006007819055600855600a805490911690553480156200003757600080fd5b50604051620012ca380380620012ca8339810160408190526200005a916200036b565b83518490849062000073906003906020850190620001f8565b50805162000089906004906020840190620001f8565b505050620000a6620000a0620000dc60201b60201c565b620000e0565b620000b2338362000132565b600980546001600160a01b0319166001600160a01b03929092169190911790555062000463915050565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166200018d5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b8060026000828254620001a1919062000400565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b828054620002069062000427565b90600052602060002090601f0160209004810192826200022a576000855562000275565b82601f106200024557805160ff191683800117855562000275565b8280016001018555821562000275579182015b828111156200027557825182559160200191906001019062000258565b506200028392915062000287565b5090565b5b8082111562000283576000815560010162000288565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620002c657600080fd5b81516001600160401b0380821115620002e357620002e36200029e565b604051601f8301601f19908116603f011681019082821181831017156200030e576200030e6200029e565b816040528381526020925086838588010111156200032b57600080fd5b600091505b838210156200034f578582018301518183018401529082019062000330565b83821115620003615760008385830101525b9695505050505050565b600080600080608085870312156200038257600080fd5b84516001600160401b03808211156200039a57600080fd5b620003a888838901620002b4565b95506020870151915080821115620003bf57600080fd5b50620003ce87828801620002b4565b60408701516060880151919550935090506001600160a01b0381168114620003f557600080fd5b939692955090935050565b600082198211156200042257634e487b7160e01b600052601160045260246000fd5b500190565b600181811c908216806200043c57607f821691505b6020821081036200045d57634e487b7160e01b600052602260045260246000fd5b50919050565b610e5780620004736000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806367e4d36c116100c3578063a457c2d71161007c578063a457c2d7146102b9578063a9059cbb146102cc578063bd67d238146102df578063dd62ed3e146102fa578063f2fde38b1461030d578063ff7a871e1461032057600080fd5b806367e4d36c1461024957806370a082311461025c578063715018a6146102855780638da5cb5b1461028d57806395d89b411461029e5780639e0ab46a146102a657600080fd5b8063313ce56711610115578063313ce567146101e357806331503ec4146101f257806339509351146102075780634650b2951461021a57806352af68071461022d578063675499451461024057600080fd5b806306fdde0314610152578063095ea7b31461017057806318160ddd1461019357806323b872dd146101a557806330b2d84d146101b8575b600080fd5b61015a610329565b6040516101679190610c13565b60405180910390f35b61018361017e366004610c84565b6103bb565b6040519015158152602001610167565b6002545b604051908152602001610167565b6101836101b3366004610cae565b6103d3565b600a546101cb906001600160a01b031681565b6040516001600160a01b039091168152602001610167565b60405160128152602001610167565b610205610200366004610cea565b6103f7565b005b610183610215366004610c84565b610421565b610205610228366004610cea565b610443565b61020561023b366004610d0c565b61046d565b61019760075481565b6006546101cb906001600160a01b031681565b61019761026a366004610cea565b6001600160a01b031660009081526020819052604090205490565b610205610480565b6005546001600160a01b03166101cb565b61015a610494565b6102056102b4366004610cea565b6104a3565b6101836102c7366004610c84565b6104cd565b6101836102da366004610c84565b61054d565b60075460085460408051928352602083019190915201610167565b610197610308366004610d2e565b61055b565b61020561031b366004610cea565b610586565b61019760085481565b60606003805461033890610d61565b80601f016020809104026020016040519081016040528092919081815260200182805461036490610d61565b80156103b15780601f10610386576101008083540402835291602001916103b1565b820191906000526020600020905b81548152906001019060200180831161039457829003601f168201915b5050505050905090565b6000336103c98185856105ff565b5060019392505050565b6000336103e1858285610724565b6103ec85858561079e565b506001949350505050565b6103ff610899565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6000336103c9818585610434838361055b565b61043e9190610db1565b6105ff565b61044b610899565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b610475610899565b600791909155600855565b610488610899565b61049260006108f3565b565b60606004805461033890610d61565b6104ab610899565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b600033816104db828661055b565b9050838110156105405760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6103ec82868684036105ff565b6000336103c981858561079e565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61058e610899565b6001600160a01b0381166105f35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610537565b6105fc816108f3565b50565b6001600160a01b0383166106615760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610537565b6001600160a01b0382166106c25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610537565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000610730848461055b565b90506000198114610798578181101561078b5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610537565b61079884848484036105ff565b50505050565b6007546008546005546001600160a01b03868116911614806107cd57506005546001600160a01b038581169116145b806107e557506006546001600160a01b038581169116145b806107fd5750600a546001600160a01b038681169116145b15610809575060009050805b600060646108178486610dc9565b6108219190610de8565b9050600060646108318487610dc9565b61083b9190610de8565b905060008161084a8488610e0a565b6108549190610e0a565b9050610861888883610945565b821561087f5760095461087f9089906001600160a01b031685610945565b811561088f5761088f8883610ae9565b5050505050505050565b6005546001600160a01b031633146104925760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610537565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0383166109a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610537565b6001600160a01b038216610a0b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610537565b6001600160a01b03831660009081526020819052604090205481811015610a835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610537565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610798565b6001600160a01b038216610b495760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610537565b6001600160a01b03821660009081526020819052604090205481811015610bbd5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610537565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610717565b600060208083528351808285015260005b81811015610c4057858101830151858201604001528201610c24565b81811115610c52576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610c7f57600080fd5b919050565b60008060408385031215610c9757600080fd5b610ca083610c68565b946020939093013593505050565b600080600060608486031215610cc357600080fd5b610ccc84610c68565b9250610cda60208501610c68565b9150604084013590509250925092565b600060208284031215610cfc57600080fd5b610d0582610c68565b9392505050565b60008060408385031215610d1f57600080fd5b50508035926020909101359150565b60008060408385031215610d4157600080fd5b610d4a83610c68565b9150610d5860208401610c68565b90509250929050565b600181811c90821680610d7557607f821691505b602082108103610d9557634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610dc457610dc4610d9b565b500190565b6000816000190483118215151615610de357610de3610d9b565b500290565b600082610e0557634e487b7160e01b600052601260045260246000fd5b500490565b600082821015610e1c57610e1c610d9b565b50039056fea26469706673582212209870f891c56339095d258fe2add095d0cb48cd8d42749b1d9f12f4a81f88fe0f64736f6c634300080e0033608060405234801561001057600080fd5b5060405162006db038038062006db083398101604081905261003191610195565b600060405161003f9061016b565b604051809103906000f08015801561005b573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b039290921691821790556040805163a217fddf60e01b81529051632f2ff15d91839163a217fddf916004808201926020929091908290030181865afa1580156100be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e291906101c8565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b15801561012157600080fd5b505af1158015610135573d6000803e3d6000fd5b5050505050600280546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790556101e1565b610c1a806200619683390190565b80516001600160a01b038116811461019057600080fd5b919050565b600080604083850312156101a857600080fd5b6101b183610179565b91506101bf60208401610179565b90509250929050565b6000602082840312156101da57600080fd5b5051919050565b615fa580620001f16000396000f3fe60806040523480156200001157600080fd5b5060043610620000935760003560e01c80633fc8cef311620000625780633fc8cef3146200010c5780635f539d691462000120578063a3574c5b1462000137578063e9e15b4f146200014b57600080fd5b80631755ff211462000098578063276184ae14620000c85780632a6bc79814620000dc57806333c3764214620000f5575b600080fd5b600454620000ac906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b600254620000ac906001600160a01b031681565b620000f3620000ed36600462000742565b62000162565b005b620000ac62000106366004620007ad565b620003d7565b600354620000ac906001600160a01b031681565b620000f362000131366004620007e0565b62000402565b600054620000ac906001600160a01b031681565b620000f36200015c366004620007e0565b6200055d565b6000546040805163a217fddf60e01b8152905133926001600160a01b0316916391d1485491839163a217fddf9160048083019260209291908290030181865afa158015620001b4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001da919062000807565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b0384166024820152604401602060405180830381865afa15801562000226573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200024c919062000821565b620002745760405162461bcd60e51b81526004016200026b9062000845565b60405180910390fd5b6004546001600160a01b0316620002c55760405162461bcd60e51b8152602060048201526014602482015273141bdbdb081859191c995cdcc81b9bdd081cd95d60621b60448201526064016200026b565b600254600080546003546040519293879387936001600160a01b0392831693908316921690620002f59062000689565b62000305959493929190620008c5565b604051809103906000f08015801562000322573d6000803e3d6000fd5b506004805460405163065bd2c760e11b81526001600160a01b039182169281019290925291925090821690630cb7a58e90602401600060405180830381600087803b1580156200037157600080fd5b505af115801562000386573d6000803e3d6000fd5b50505050620003958162000402565b6040516001600160a01b03821681527fc22a3bb33e309684602010c6dc271767c0bf5d58f1904b89e8c72fc17bf144b99060200160405180910390a150505050565b60018181548110620003e857600080fd5b6000918252602090912001546001600160a01b0316905081565b6000546040805163a217fddf60e01b8152905133926001600160a01b0316916391d1485491839163a217fddf9160048083019260209291908290030181865afa15801562000454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200047a919062000807565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b0384166024820152604401602060405180830381865afa158015620004c6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004ec919062000821565b6200050b5760405162461bcd60e51b81526004016200026b9062000845565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546040805163a217fddf60e01b8152905133926001600160a01b0316916391d1485491839163a217fddf9160048083019260209291908290030181865afa158015620005af573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005d5919062000807565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b0384166024820152604401602060405180830381865afa15801562000621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000647919062000821565b620006665760405162461bcd60e51b81526004016200026b9062000845565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b615647806200092983390190565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620006bf57600080fd5b813567ffffffffffffffff80821115620006dd57620006dd62000697565b604051601f8301601f19908116603f0116810190828211818310171562000708576200070862000697565b816040528381528660208588010111156200072257600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156200075657600080fd5b823567ffffffffffffffff808211156200076f57600080fd5b6200077d86838701620006ad565b935060208501359150808211156200079457600080fd5b50620007a385828601620006ad565b9150509250929050565b600060208284031215620007c057600080fd5b5035919050565b6001600160a01b0381168114620007dd57600080fd5b50565b600060208284031215620007f357600080fd5b81356200080081620007c7565b9392505050565b6000602082840312156200081a57600080fd5b5051919050565b6000602082840312156200083457600080fd5b815180151581146200080057600080fd5b6020808252601690820152751051135253881c9bdb19481a5cc81c995c5d5a5c995960521b604082015260600190565b6000815180845260005b818110156200089d576020818501810151868301820152016200087f565b81811115620008b0576000602083870101525b50601f01601f19169290920160200192915050565b60c081526000620008da60c083018862000875565b8281036020840152620008ee818862000875565b8381036040850152600081526001600160a01b03968716606085015294861660808401525050921660a0909201919091526020019291505056fe60c06040526007608081905266697066733a2f2f60c81b60a09081526200002a91600a91906200026d565b5060408051808201909152600e8082526d17b6b2ba30b230ba30973539b7b760911b60209092019182526200006291600b916200026d565b50600c805461ffff19166101001790553480156200007f57600080fd5b506040516200564738038062005647833981016040819052620000a2916200040b565b8184620000af8162000254565b506001600160a01b038116620001ce57604051620000cd90620002fc565b604051809103906000f080158015620000ea573d6000803e3d6000fd5b50600480546001600160a01b0319166001600160a01b039290921691821781556040805163a217fddf60e01b81529051632f2ff15d92849263a217fddf92818301926020928290030181865afa15801562000149573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016f9190620004d3565b6040516001600160e01b031960e084901b1681526004810191909152336024820152604401600060405180830381600087803b158015620001af57600080fd5b505af1158015620001c4573d6000803e3d6000fd5b50505050620001ea565b600480546001600160a01b0319166001600160a01b0383161790555b5060016005558551620002059060079060208901906200026d565b5084516200021b9060089060208801906200026d565b50600680546001600160a01b039485166001600160a01b0319918216179091556009805492909416911617909155506200052992505050565b8051620002699060029060208401906200026d565b5050565b8280546200027b90620004ed565b90600052602060002090601f0160209004810192826200029f5760008555620002ea565b82601f10620002ba57805160ff1916838001178555620002ea565b82800160010185558215620002ea579182015b82811115620002ea578251825591602001919060010190620002cd565b50620002f89291506200030a565b5090565b610c1a8062004a2d83390190565b5b80821115620002f857600081556001016200030b565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200034957600080fd5b81516001600160401b038082111562000366576200036662000321565b604051601f8301601f19908116603f0116810190828211818310171562000391576200039162000321565b81604052838152602092508683858801011115620003ae57600080fd5b600091505b83821015620003d25785820183015181830184015290820190620003b3565b83821115620003e45760008385830101525b9695505050505050565b80516001600160a01b03811681146200040657600080fd5b919050565b60008060008060008060c087890312156200042557600080fd5b86516001600160401b03808211156200043d57600080fd5b6200044b8a838b0162000337565b975060208901519150808211156200046257600080fd5b620004708a838b0162000337565b965060408901519150808211156200048757600080fd5b506200049689828a0162000337565b945050620004a760608801620003ee565b9250620004b760808801620003ee565b9150620004c760a08801620003ee565b90509295509295509295565b600060208284031215620004e657600080fd5b5051919050565b600181811c908216806200050257607f821691505b6020821081036200052357634e487b7160e01b600052602260045260246000fd5b50919050565b6144f480620005396000396000f3fe608060405234801561001057600080fd5b50600436106102685760003560e01c8063559e775b11610151578063b483cec3116100c3578063e0a8085311610087578063e0a808531461057f578063e676fc1814610592578063e985e9c5146105b9578063f242432a146105f5578063f55ebd2a14610608578063f74821fb1461062157600080fd5b8063b483cec31461050b578063b6e4203514610531578063bd85b03914610544578063c74b053514610564578063e0100a4d1461057757600080fd5b80639abc8320116101155780639abc8320146104905780639d76ea5814610498578063a0bcfc7f146104ab578063a22cb465146104be578063a3574c5b146104d1578063a853211a146104e457600080fd5b8063559e775b146104485780635c2c481c1461045b5780635c975abb1461046e5780635fd8c7101461048057806395d89b411461048857600080fd5b80632eb2c2d6116101ea57806341bec0d2116101ae57806341bec0d2146103cb5780634e1273f4146103de5780634f558e79146103fe5780634fa40cf61461042057806351830227146104335780635503a0e81461044057600080fd5b80632eb2c2d61461034757806331d84a1c1461035a578063348a0cdc1461036d57806337da577c1461038d5780633fc8cef3146103a057600080fd5b80630e89341c116102315780630e89341c146102f35780631387a98f1461030657806316ba10e01461030e57806316c38b3c146103215780631b2ef1ca1461033457600080fd5b8062fdd58e1461026d57806301ffc9a7146102935780630442bfa8146102b657806306fdde03146102cb5780630cb7a58e146102e0575b600080fd5b61028061027b3660046136d2565b610634565b6040519081526020015b60405180910390f35b6102a66102a1366004613714565b6106ca565b604051901515815260200161028a565b6102c96102c4366004613731565b6106f5565b005b6102d36108f6565b60405161028a91906137a0565b6102c96102ee3660046137b3565b610984565b6102d36103013660046137d0565b610aa0565b610280610b3e565b6102c961031c36600461389e565b610c05565b6102c961032f3660046138e8565b610d0e565b6102c9610342366004613731565b610e1a565b6102c9610355366004613999565b610e29565b6102c9610368366004613a46565b610e75565b61038061037b366004613a7b565b6112fa565b60405161028a9190613aef565b6102c961039b366004613731565b611448565b6009546103b3906001600160a01b031681565b6040516001600160a01b03909116815260200161028a565b6102c96103d93660046137b3565b6116bc565b6103f16103ec366004613b51565b6117d0565b60405161028a9190613c58565b6102a661040c3660046137d0565b600090815260036020526040902054151590565b6102c961042e366004613c6b565b6118f1565b600c546102a69060ff1681565b6102d3611b02565b6102806104563660046137d0565b611b0f565b6102c9610469366004613ca7565b611bca565b600c546102a690610100900460ff1681565b6102c9611dd8565b6102d3611fb6565b6102d3611fc3565b6006546103b3906001600160a01b031681565b6102c96104b936600461389e565b611fd0565b6102c96104cc366004613cd7565b6120d4565b6004546103b3906001600160a01b031681565b6102807f21d1167972f621f75904fb065136bc8b53c7ba1c60ccd3a7758fbee465851e9c81565b61051e6105193660046137d0565b6120df565b60405161028a9796959493929190613d05565b6102c961053f366004613731565b6121bd565b6102806105523660046137d0565b60009081526003602052604090205490565b6102c9610572366004613d4c565b6123be565b6103f16125d2565b6102c961058d3660046138e8565b612685565b6105a06355405a2760e01b81565b6040516001600160e01b0319909116815260200161028a565b6102a66105c7366004613d84565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6102c9610603366004613db2565b61278a565b600c546103b3906201000090046001600160a01b031681565b6102c961062f366004613e1a565b6127cf565b60006001600160a01b0383166106a45760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b031982166355405a2760e01b14806106ef57506106ef82612b47565b92915050565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa158015610747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076b9190613e6d565b836040518363ffffffff1660e01b8152600401610789929190613e86565b602060405180830381865afa1580156107a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ca9190613e9d565b806108a45750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015610821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190613e6d565b836040518363ffffffff1660e01b8152600401610863929190613e86565b602060405180830381865afa158015610880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a49190613e9d565b6108c05760405162461bcd60e51b815260040161069b90613eba565b81600d6108cc85612b97565b815481106108dc576108dc613efb565b906000526020600020906007020160010181905550505050565b6007805461090390613f11565b80601f016020809104026020016040519081016040528092919081815260200182805461092f90613f11565b801561097c5780601f106109515761010080835404028352916020019161097c565b820191906000526020600020905b81548152906001019060200180831161095f57829003601f168201915b505050505081565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa1580156109d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fa9190613e6d565b836040518363ffffffff1660e01b8152600401610a18929190613e86565b602060405180830381865afa158015610a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a599190613e9d565b610a755760405162461bcd60e51b815260040161069b90613f45565b50600c80546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b60608060005b600d54811015610b375783600d8281548110610ac457610ac4613efb565b90600052602060002090600702016000015403610b2757600a600d8281548110610af057610af0613efb565b9060005260206000209060070201600501600b604051602001610b159392919061400e565b60405160208183030381529060405291505b610b3081614042565b9050610aa6565b5092915050565b600080600c60029054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610b94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb8919061406d565b50505050505090506000816001600160a01b0316826001600160a01b0316610be0919061410c565b9050670de0b6b3a76400006000610bfc8383600160c01b612c1e565b95945050505050565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015610c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7b9190613e6d565b836040518363ffffffff1660e01b8152600401610c99929190613e86565b602060405180830381865afa158015610cb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cda9190613e9d565b610cf65760405162461bcd60e51b815260040161069b90613f45565b8151610d0990600b906020850190613621565b505050565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015610d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d849190613e6d565b836040518363ffffffff1660e01b8152600401610da2929190613e86565b602060405180830381865afa158015610dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de39190613e9d565b610dff5760405162461bcd60e51b815260040161069b90613f45565b50600c80549115156101000261ff0019909216919091179055565b610e25338383610e75565b5050565b6001600160a01b038516331480610e455750610e4585336105c7565b610e615760405162461bcd60e51b815260040161069b9061412b565b610e6e8585858585612cd1565b5050505050565b816000805b600d54811015610ec65782600d8281548110610e9857610e98613efb565b90600052602060002090600702016000015403610eb457600191505b80610ebe81614042565b915050610e7a565b5080610f035760405162461bcd60e51b815260206004820152600c60248201526b1259081b9bdd08199bdd5b9960a21b604482015260640161069b565b8284600d610f1082612b97565b81548110610f2057610f20613efb565b90600052602060002090600702016002015482610f498360009081526003602052604090205490565b610f539190614179565b1115610f715760405162461bcd60e51b815260040161069b90614191565b600c54610100900460ff1615610fbf5760405162461bcd60e51b815260206004820152601360248201527221b7b73a3930b1ba1034b9903830bab9b2b21760691b604482015260640161069b565b610fc7612ebc565b60005b600d548110156112e65786600d8281548110610fe857610fe8613efb565b906000526020600020906007020160000154036112d457600061100a88611b0f565b9050611016878261410c565b6006546001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561106c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110909190613e6d565b10156110d65760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e742066756e647321212160581b604482015260640161069b565b600d82815481106110e9576110e9613efb565b90600052602060002090600702016002015460001461118b57600d828154811061111557611115613efb565b9060005260206000209060070201600201548761113e8a60009081526003602052604090205490565b6111489190614179565b111561118b5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b604482015260640161069b565b600d828154811061119e5761119e613efb565b600091825260209091206003600790920201015460ff166111f85760405162461bcd60e51b8152602060048201526014602482015273139195081b9bdd081c995b19585cd959081e595d60621b604482015260640161069b565b6006546001600160a01b03166323b872dd33306112158b8661410c565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af1158015611269573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128d9190613e9d565b5042600d83815481106112a2576112a2613efb565b9060005260206000209060070201600601819055506112d289898960405180602001604052806000815250612f15565b505b806112de81614042565b915050610fca565b506112f16001600555565b50505050505050565b60606000826001600160401b03811115611316576113166137e9565b60405190808252806020026020018201604052801561134957816020015b60608152602001906001900390816113345790505b50905060005b83811015611440576000803087878581811061136d5761136d613efb565b905060200281019061137f91906141bd565b60405161138d92919061420a565b600060405180830381855af49150503d80600081146113c8576040519150601f19603f3d011682016040523d82523d6000602084013e6113cd565b606091505b50915091508161140d5760405162461bcd60e51b815260206004820152600b60248201526a18d85b1b0819985a5b195960aa1b604482015260640161069b565b8084848151811061142057611420613efb565b60200260200101819052505050808061143890614042565b91505061134f565b509392505050565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa15801561149a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114be9190613e6d565b836040518363ffffffff1660e01b81526004016114dc929190613e86565b602060405180830381865afa1580156114f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151d9190613e9d565b806115f75750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015611574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115989190613e6d565b836040518363ffffffff1660e01b81526004016115b6929190613e86565b602060405180830381865afa1580156115d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f79190613e9d565b6116135760405162461bcd60e51b815260040161069b90613eba565b60008381526003602052604090205482116116865760405162461bcd60e51b815260206004820152602d60248201527f4d617820737570706c792063616e206e6f74206265206c657373207468616e2060448201526c3a37ba30b61039bab838363c9760991b606482015260840161069b565b81600d61169285612b97565b815481106116a2576116a2613efb565b906000526020600020906007020160020181905550505050565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa15801561170e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117329190613e6d565b836040518363ffffffff1660e01b8152600401611750929190613e86565b602060405180830381865afa15801561176d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117919190613e9d565b6117ad5760405162461bcd60e51b815260040161069b90613f45565b50600680546001600160a01b0319166001600160a01b0392909216919091179055565b606081518351146118355760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b606482015260840161069b565b600083516001600160401b03811115611850576118506137e9565b604051908082528060200260200182016040528015611879578160200160208202803683370190505b50905060005b8451811015611440576118c485828151811061189d5761189d613efb565b60200260200101518583815181106118b7576118b7613efb565b6020026020010151610634565b8282815181106118d6576118d6613efb565b60209081029190910101526118ea81614042565b905061187f565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa158015611943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119679190613e6d565b836040518363ffffffff1660e01b8152600401611985929190613e86565b602060405180830381865afa1580156119a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c69190613e9d565b80611aa05750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015611a1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a419190613e6d565b836040518363ffffffff1660e01b8152600401611a5f929190613e86565b602060405180830381865afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa09190613e9d565b611abc5760405162461bcd60e51b815260040161069b90613eba565b81600d611ac885612b97565b81548110611ad857611ad8613efb565b90600052602060002090600702016005019080519060200190611afc929190613621565b50505050565b600b805461090390613f11565b6009546006546000916001600160a01b0390811691161115611b7d57670de0b6b3a7640000611b3c610b3e565b600d611b4785612b97565b81548110611b5757611b57613efb565b906000526020600020906007020160010154611b73919061410c565b6106ef919061421a565b611b85610b3e565b600d611b9084612b97565b81548110611ba057611ba0613efb565b906000526020600020906007020160010154670de0b6b3a7640000611b73919061410c565b919050565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa158015611c1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c409190613e6d565b836040518363ffffffff1660e01b8152600401611c5e929190613e86565b602060405180830381865afa158015611c7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9f9190613e9d565b80611d795750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015611cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1a9190613e6d565b836040518363ffffffff1660e01b8152600401611d38929190613e86565b602060405180830381865afa158015611d55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d799190613e9d565b611d955760405162461bcd60e51b815260040161069b90613eba565b81600d611da185612b97565b81548110611db157611db1613efb565b60009182526020909120600790910201600301805460ff1916911515919091179055505050565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015611e2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4e9190613e6d565b836040518363ffffffff1660e01b8152600401611e6c929190613e86565b602060405180830381865afa158015611e89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ead9190613e9d565b611ec95760405162461bcd60e51b815260040161069b90613f45565b6006546001600160a01b031663a9059cbb336006546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f479190613e6d565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611f92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e259190613e9d565b6008805461090390613f11565b600a805461090390613f11565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa158015612022573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120469190613e6d565b836040518363ffffffff1660e01b8152600401612064929190613e86565b602060405180830381865afa158015612081573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a59190613e9d565b6120c15760405162461bcd60e51b815260040161069b90613f45565b8151610d0990600a906020850190613621565b610e2533838361302f565b600d81815481106120ef57600080fd5b60009182526020909120600790910201805460018201546002830154600384015460048501546005860180549597509395929460ff9092169390929161213490613f11565b80601f016020809104026020016040519081016040528092919081815260200182805461216090613f11565b80156121ad5780601f10612182576101008083540402835291602001916121ad565b820191906000526020600020905b81548152906001019060200180831161219057829003601f168201915b5050505050908060060154905087565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122339190613e6d565b836040518363ffffffff1660e01b8152600401612251929190613e86565b602060405180830381865afa15801561226e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122929190613e9d565b8061236c5750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190613e6d565b836040518363ffffffff1660e01b815260040161232b929190613e86565b602060405180830381865afa158015612348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236c9190613e9d565b6123885760405162461bcd60e51b815260040161069b90613eba565b81600d61239485612b97565b815481106123a4576123a4613efb565b906000526020600020906007020160040181905550505050565b8281600d6123cb82612b97565b815481106123db576123db613efb565b906000526020600020906007020160020154826124048360009081526003602052604090205490565b61240e9190614179565b111561242c5760405162461bcd60e51b815260040161069b90614191565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa15801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a29190613e6d565b836040518363ffffffff1660e01b81526004016124c0929190613e86565b602060405180830381865afa1580156124dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125019190613e9d565b61251d5760405162461bcd60e51b815260040161069b90613f45565b600061252885612b97565b9050600d818154811061253d5761253d613efb565b906000526020600020906007020160020154876125668760009081526003602052604090205490565b6125709190614179565b111561258e5760405162461bcd60e51b815260040161069b90614191565b42600d82815481106125a2576125a2613efb565b9060005260206000209060070201600601819055506112f186868960405180602001604052806000815250612f15565b600d546060906000906001600160401b038111156125f2576125f26137e9565b60405190808252806020026020018201604052801561261b578160200160208202803683370190505b50905060005b600d5481101561267f57600d818154811061263e5761263e613efb565b90600052602060002090600702016000015482828151811061266257612662613efb565b60209081029190910101528061267781614042565b915050612621565b50919050565b33600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa1580156126d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fb9190613e6d565b836040518363ffffffff1660e01b8152600401612719929190613e86565b602060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a9190613e9d565b6127765760405162461bcd60e51b815260040161069b90613f45565b50600c805460ff1916911515919091179055565b6001600160a01b0385163314806127a657506127a685336105c7565b6127c25760405162461bcd60e51b815260040161069b9061412b565b610e6e858585858561310f565b336004805460408051635429908d60e11b815290516001600160a01b03909216926391d1485492849263a853211a92818101926020929091908290030181865afa158015612821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128459190613e6d565b836040518363ffffffff1660e01b8152600401612863929190613e86565b602060405180830381865afa158015612880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a49190613e9d565b8061297e5750600480546040805163a217fddf60e01b815290516001600160a01b03909216926391d1485492849263a217fddf92818101926020929091908290030181865afa1580156128fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061291f9190613e6d565b836040518363ffffffff1660e01b815260040161293d929190613e86565b602060405180830381865afa15801561295a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297e9190613e9d565b61299a5760405162461bcd60e51b815260040161069b90613eba565b6040805160e081018252600d805480835260208084018b81529484018a815289151560608601908152608086018a815260a087018a8152600060c089018190526001870188559690965286517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5600790960295860190815597517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb686015591517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb7850155517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb88401805460ff1916911515919091179055517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb983015591518051939485949093612aee937fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eba01920190613621565b5060c0820151816006015550508587600d805490507f2b64eda45fa54e08db9855b12bf92663607d88be8ab508185d50b6e1cb6102df888888604051612b369392919061423c565b60405180910390a450505050505050565b60006001600160e01b03198216636cdb3d1360e11b1480612b7857506001600160e01b031982166303a24d0760e21b145b806106ef57506301ffc9a760e01b6001600160e01b03198316146106ef565b6000805b600d54811015612be65782600d8281548110612bb957612bb9613efb565b90600052602060002090600702016000015403612bd65792915050565b612bdf81614042565b9050612b9b565b5060405162461bcd60e51b815260206004820152600c60248201526b1259081b9bdd08199bdd5b9960a21b604482015260640161069b565b6000808060001985870985870292508281108382030391505080600003612c575760008411612c4c57600080fd5b508290049050612cca565b808411612c6357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b8151835114612d335760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161069b565b6001600160a01b038416612d595760405162461bcd60e51b815260040161069b9061425d565b33612d68818787878787613247565b60005b8451811015612e4e576000858281518110612d8857612d88613efb565b602002602001015190506000858381518110612da657612da6613efb565b602090810291909101810151600084815280835260408082206001600160a01b038e168352909352919091205490915081811015612df65760405162461bcd60e51b815260040161069b906142a2565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290612e33908490614179565b9250508190555050505080612e4790614042565b9050612d6b565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051612e9e9291906142ec565b60405180910390a4612eb48187878787876133c0565b505050505050565b600260055403612f0e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161069b565b6002600555565b6001600160a01b038416612f755760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161069b565b336000612f818561351b565b90506000612f8e8561351b565b9050612f9f83600089858589613247565b6000868152602081815260408083206001600160a01b038b16845290915281208054879290612fcf908490614179565b909155505060408051878152602081018790526001600160a01b03808a1692600092918716917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46112f183600089898989613566565b816001600160a01b0316836001600160a01b0316036130a25760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b606482015260840161069b565b6001600160a01b03838116600081815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0384166131355760405162461bcd60e51b815260040161069b9061425d565b3360006131418561351b565b9050600061314e8561351b565b905061315e838989858589613247565b6000868152602081815260408083206001600160a01b038c1684529091529020548581101561319f5760405162461bcd60e51b815260040161069b906142a2565b6000878152602081815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906131dc908490614179565b909155505060408051888152602081018890526001600160a01b03808b16928c821692918816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461323c848a8a8a8a8a613566565b505050505050505050565b6001600160a01b0385166132ce5760005b83518110156132cc5782818151811061327357613273613efb565b60200260200101516003600086848151811061329157613291613efb565b6020026020010151815260200190815260200160002060008282546132b69190614179565b909155506132c5905081614042565b9050613258565b505b6001600160a01b038416612eb45760005b83518110156112f15760008482815181106132fc576132fc613efb565b60200260200101519050600084838151811061331a5761331a613efb565b602002602001015190506000600360008481526020019081526020016000205490508181101561339d5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b606482015260840161069b565b600092835260036020526040909220910390556133b981614042565b90506132df565b6001600160a01b0384163b15612eb45760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906134049089908990889088908890600401614311565b6020604051808303816000875af192505050801561343f575060408051601f3d908101601f1916820190925261343c9181019061436f565b60015b6134eb5761344b61438c565b806308c379a003613484575061345f6143a8565b8061346a5750613486565b8060405162461bcd60e51b815260040161069b91906137a0565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b606482015260840161069b565b6001600160e01b0319811663bc197c8160e01b146112f15760405162461bcd60e51b815260040161069b90614431565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061355557613555613efb565b602090810291909101015292915050565b6001600160a01b0384163b15612eb45760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906135aa9089908990889088908890600401614479565b6020604051808303816000875af19250505080156135e5575060408051601f3d908101601f191682019092526135e29181019061436f565b60015b6135f15761344b61438c565b6001600160e01b0319811663f23a6e6160e01b146112f15760405162461bcd60e51b815260040161069b90614431565b82805461362d90613f11565b90600052602060002090601f01602090048101928261364f5760008555613695565b82601f1061366857805160ff1916838001178555613695565b82800160010185558215613695579182015b8281111561369557825182559160200191906001019061367a565b506136a19291506136a5565b5090565b5b808211156136a157600081556001016136a6565b6001600160a01b03811681146136cf57600080fd5b50565b600080604083850312156136e557600080fd5b82356136f0816136ba565b946020939093013593505050565b6001600160e01b0319811681146136cf57600080fd5b60006020828403121561372657600080fd5b8135612cca816136fe565b6000806040838503121561374457600080fd5b50508035926020909101359150565b6000815180845260005b818110156137795760208185018101518683018201520161375d565b8181111561378b576000602083870101525b50601f01601f19169290920160200192915050565b602081526000612cca6020830184613753565b6000602082840312156137c557600080fd5b8135612cca816136ba565b6000602082840312156137e257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715613824576138246137e9565b6040525050565b600082601f83011261383c57600080fd5b81356001600160401b03811115613855576138556137e9565b60405161386c601f8301601f1916602001826137ff565b81815284602083860101111561388157600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156138b057600080fd5b81356001600160401b038111156138c657600080fd5b6138d28482850161382b565b949350505050565b80151581146136cf57600080fd5b6000602082840312156138fa57600080fd5b8135612cca816138da565b60006001600160401b0382111561391e5761391e6137e9565b5060051b60200190565b600082601f83011261393957600080fd5b8135602061394682613905565b60405161395382826137ff565b83815260059390931b850182019282810191508684111561397357600080fd5b8286015b8481101561398e5780358352918301918301613977565b509695505050505050565b600080600080600060a086880312156139b157600080fd5b85356139bc816136ba565b945060208601356139cc816136ba565b935060408601356001600160401b03808211156139e857600080fd5b6139f489838a01613928565b94506060880135915080821115613a0a57600080fd5b613a1689838a01613928565b93506080880135915080821115613a2c57600080fd5b50613a398882890161382b565b9150509295509295909350565b600080600060608486031215613a5b57600080fd5b8335613a66816136ba565b95602085013595506040909401359392505050565b60008060208385031215613a8e57600080fd5b82356001600160401b0380821115613aa557600080fd5b818501915085601f830112613ab957600080fd5b813581811115613ac857600080fd5b8660208260051b8501011115613add57600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613b4457603f19888603018452613b32858351613753565b94509285019290850190600101613b16565b5092979650505050505050565b60008060408385031215613b6457600080fd5b82356001600160401b0380821115613b7b57600080fd5b818501915085601f830112613b8f57600080fd5b81356020613b9c82613905565b604051613ba982826137ff565b83815260059390931b8501820192828101915089841115613bc957600080fd5b948201945b83861015613bf0578535613be1816136ba565b82529482019490820190613bce565b96505086013592505080821115613c0657600080fd5b50613c1385828601613928565b9150509250929050565b600081518084526020808501945080840160005b83811015613c4d57815187529582019590820190600101613c31565b509495945050505050565b602081526000612cca6020830184613c1d565b60008060408385031215613c7e57600080fd5b8235915060208301356001600160401b03811115613c9b57600080fd5b613c138582860161382b565b60008060408385031215613cba57600080fd5b823591506020830135613ccc816138da565b809150509250929050565b60008060408385031215613cea57600080fd5b8235613cf5816136ba565b91506020830135613ccc816138da565b878152866020820152856040820152841515606082015283608082015260e060a08201526000613d3860e0830185613753565b90508260c083015298975050505050505050565b600080600060608486031215613d6157600080fd5b833592506020840135613d73816136ba565b929592945050506040919091013590565b60008060408385031215613d9757600080fd5b8235613da2816136ba565b91506020830135613ccc816136ba565b600080600080600060a08688031215613dca57600080fd5b8535613dd5816136ba565b94506020860135613de5816136ba565b9350604086013592506060860135915060808601356001600160401b03811115613e0e57600080fd5b613a398882890161382b565b600080600080600060a08688031215613e3257600080fd5b85359450602086013593506040860135613e4b816138da565b92506060860135915060808601356001600160401b03811115613e0e57600080fd5b600060208284031215613e7f57600080fd5b5051919050565b9182526001600160a01b0316602082015260400190565b600060208284031215613eaf57600080fd5b8151612cca816138da565b60208082526021908201527f454449544f5220726f6c65206f722068696768657220697320726571756972656040820152601960fa1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680613f2557607f821691505b60208210810361267f57634e487b7160e01b600052602260045260246000fd5b6020808252601690820152751051135253881c9bdb19481a5cc81c995c5d5a5c995960521b604082015260600190565b8054600090600181811c9080831680613f8f57607f831692505b60208084108203613fb057634e487b7160e01b600052602260045260246000fd5b818015613fc45760018114613fd557614002565b60ff19861689528489019650614002565b60008881526020902060005b86811015613ffa5781548b820152908501908301613fe1565b505084890196505b50505050505092915050565b6000610bfc6140266140208488613f75565b86613f75565b84613f75565b634e487b7160e01b600052601160045260246000fd5b6000600182016140545761405461402c565b5060010190565b805161ffff81168114611bc557600080fd5b600080600080600080600060e0888a03121561408857600080fd5b8751614093816136ba565b8097505060208801518060020b81146140ab57600080fd5b95506140b96040890161405b565b94506140c76060890161405b565b93506140d56080890161405b565b925060a088015160ff811681146140eb57600080fd5b60c08901519092506140fc816138da565b8091505092959891949750929550565b60008160001904831182151516156141265761412661402c565b500290565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b6000821982111561418c5761418c61402c565b500190565b6020808252601290820152714d617820737570706c79206578636565642160701b604082015260600190565b6000808335601e198436030181126141d457600080fd5b8301803591506001600160401b038211156141ee57600080fd5b60200191503681900382131561420357600080fd5b9250929050565b8183823760009101908152919050565b60008261423757634e487b7160e01b600052601260045260246000fd5b500490565b8315158152826020820152606060408201526000610bfc6060830184613753565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b6040815260006142ff6040830185613c1d565b8281036020840152610bfc8185613c1d565b6001600160a01b0386811682528516602082015260a06040820181905260009061433d90830186613c1d565b828103606084015261434f8186613c1d565b905082810360808401526143638185613753565b98975050505050505050565b60006020828403121561438157600080fd5b8151612cca816136fe565b600060033d11156143a55760046000803e5060005160e01c5b90565b600060443d10156143b65790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156143e557505050505090565b82850191508151818111156143fd5750505050505090565b843d87010160208285010111156144175750505050505090565b614426602082860101876137ff565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906144b390830184613753565b97965050505050505056fea264697066735822122062b8a6fcacb0e53c40cb21ff043ebb9104b7257ab3407d4f45872a02fff18b4c64736f6c634300080e0033608060405234801561001057600080fd5b5061001c600033610021565b61016a565b610035828261005e60201b6103131760201c565b60008281526001602090815260409091206100599183906103976100fd821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166100f9576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556100b83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000610112836001600160a01b03841661011b565b90505b92915050565b600081815260018301602052604081205461016257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610115565b506000610115565b610aa1806101796000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806391d148541161006657806391d148541461014f578063a217fddf14610162578063a853211a1461016a578063ca15c87314610191578063d547741f146101a457600080fd5b806301ffc9a7146100a3578063248a9ca3146100cb5780632f2ff15d146100fc57806336568abe146101115780639010d07c14610124575b600080fd5b6100b66100b1366004610835565b6101b7565b60405190151581526020015b60405180910390f35b6100ee6100d936600461085f565b60009081526020819052604090206001015490565b6040519081526020016100c2565b61010f61010a366004610878565b6101e2565b005b61010f61011f366004610878565b61020c565b6101376101323660046108b4565b61028f565b6040516001600160a01b0390911681526020016100c2565b6100b661015d366004610878565b6102ae565b6100ee600081565b6100ee7f21d1167972f621f75904fb065136bc8b53c7ba1c60ccd3a7758fbee465851e9c81565b6100ee61019f36600461085f565b6102d7565b61010f6101b2366004610878565b6102ee565b60006001600160e01b03198216635a05180f60e01b14806101dc57506101dc826103ac565b92915050565b6000828152602081905260409020600101546101fd816103e1565b61020783836103ee565b505050565b6001600160a01b03811633146102815760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61028b8282610410565b5050565b60008281526001602052604081206102a79083610432565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008181526001602052604081206101dc9061043e565b600082815260208190526040902060010154610309816103e1565b6102078383610410565b61031d82826102ae565b61028b576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556103533390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006102a7836001600160a01b038416610448565b60006001600160e01b03198216637965db0b60e01b14806101dc57506301ffc9a760e01b6001600160e01b03198316146101dc565b6103eb8133610497565b50565b6103f88282610313565b60008281526001602052604090206102079082610397565b61041a82826104f0565b60008281526001602052604090206102079082610555565b60006102a7838361056a565b60006101dc825490565b600081815260018301602052604081205461048f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556101dc565b5060006101dc565b6104a182826102ae565b61028b576104ae81610594565b6104b98360206105a6565b6040516020016104ca929190610906565b60408051601f198184030181529082905262461bcd60e51b82526102789160040161097b565b6104fa82826102ae565b1561028b576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006102a7836001600160a01b038416610742565b6000826000018281548110610581576105816109ae565b9060005260206000200154905092915050565b60606101dc6001600160a01b03831660145b606060006105b58360026109da565b6105c09060026109f9565b67ffffffffffffffff8111156105d8576105d8610a11565b6040519080825280601f01601f191660200182016040528015610602576020820181803683370190505b509050600360fc1b8160008151811061061d5761061d6109ae565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061064c5761064c6109ae565b60200101906001600160f81b031916908160001a90535060006106708460026109da565b61067b9060016109f9565b90505b60018111156106f3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106106af576106af6109ae565b1a60f81b8282815181106106c5576106c56109ae565b60200101906001600160f81b031916908160001a90535060049490941c936106ec81610a27565b905061067e565b5083156102a75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610278565b6000818152600183016020526040812054801561082b576000610766600183610a3e565b855490915060009061077a90600190610a3e565b90508181146107df57600086600001828154811061079a5761079a6109ae565b90600052602060002001549050808760000184815481106107bd576107bd6109ae565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806107f0576107f0610a55565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506101dc565b60009150506101dc565b60006020828403121561084757600080fd5b81356001600160e01b0319811681146102a757600080fd5b60006020828403121561087157600080fd5b5035919050565b6000806040838503121561088b57600080fd5b8235915060208301356001600160a01b03811681146108a957600080fd5b809150509250929050565b600080604083850312156108c757600080fd5b50508035926020909101359150565b60005b838110156108f15781810151838201526020016108d9565b83811115610900576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161093e8160178501602088016108d6565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161096f8160288401602088016108d6565b01602801949350505050565b602081526000825180602084015261099a8160408501602087016108d6565b601f01601f19169190910160400192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156109f4576109f46109c4565b500290565b60008219821115610a0c57610a0c6109c4565b500190565b634e487b7160e01b600052604160045260246000fd5b600081610a3657610a366109c4565b506000190190565b600082821015610a5057610a506109c4565b500390565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201eaf2a559b6354216b71737aa56d5cd28acb397e1c9e8a4913fd99e9f7c766c064736f6c634300080e0033a2646970667358221220aca90e5fd5bf3e1b40674687c74bcc18391a0ec1d884cdd7db89a2a989499ad664736f6c634300080e0033608060405234801561001057600080fd5b5061001c600033610021565b61016a565b610035828261005e60201b6103131760201c565b60008281526001602090815260409091206100599183906103976100fd821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166100f9576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556100b83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000610112836001600160a01b03841661011b565b90505b92915050565b600081815260018301602052604081205461016257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610115565b506000610115565b610aa1806101796000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806391d148541161006657806391d148541461014f578063a217fddf14610162578063a853211a1461016a578063ca15c87314610191578063d547741f146101a457600080fd5b806301ffc9a7146100a3578063248a9ca3146100cb5780632f2ff15d146100fc57806336568abe146101115780639010d07c14610124575b600080fd5b6100b66100b1366004610835565b6101b7565b60405190151581526020015b60405180910390f35b6100ee6100d936600461085f565b60009081526020819052604090206001015490565b6040519081526020016100c2565b61010f61010a366004610878565b6101e2565b005b61010f61011f366004610878565b61020c565b6101376101323660046108b4565b61028f565b6040516001600160a01b0390911681526020016100c2565b6100b661015d366004610878565b6102ae565b6100ee600081565b6100ee7f21d1167972f621f75904fb065136bc8b53c7ba1c60ccd3a7758fbee465851e9c81565b6100ee61019f36600461085f565b6102d7565b61010f6101b2366004610878565b6102ee565b60006001600160e01b03198216635a05180f60e01b14806101dc57506101dc826103ac565b92915050565b6000828152602081905260409020600101546101fd816103e1565b61020783836103ee565b505050565b6001600160a01b03811633146102815760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61028b8282610410565b5050565b60008281526001602052604081206102a79083610432565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60008181526001602052604081206101dc9061043e565b600082815260208190526040902060010154610309816103e1565b6102078383610410565b61031d82826102ae565b61028b576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556103533390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006102a7836001600160a01b038416610448565b60006001600160e01b03198216637965db0b60e01b14806101dc57506301ffc9a760e01b6001600160e01b03198316146101dc565b6103eb8133610497565b50565b6103f88282610313565b60008281526001602052604090206102079082610397565b61041a82826104f0565b60008281526001602052604090206102079082610555565b60006102a7838361056a565b60006101dc825490565b600081815260018301602052604081205461048f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556101dc565b5060006101dc565b6104a182826102ae565b61028b576104ae81610594565b6104b98360206105a6565b6040516020016104ca929190610906565b60408051601f198184030181529082905262461bcd60e51b82526102789160040161097b565b6104fa82826102ae565b1561028b576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006102a7836001600160a01b038416610742565b6000826000018281548110610581576105816109ae565b9060005260206000200154905092915050565b60606101dc6001600160a01b03831660145b606060006105b58360026109da565b6105c09060026109f9565b67ffffffffffffffff8111156105d8576105d8610a11565b6040519080825280601f01601f191660200182016040528015610602576020820181803683370190505b509050600360fc1b8160008151811061061d5761061d6109ae565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061064c5761064c6109ae565b60200101906001600160f81b031916908160001a90535060006106708460026109da565b61067b9060016109f9565b90505b60018111156106f3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106106af576106af6109ae565b1a60f81b8282815181106106c5576106c56109ae565b60200101906001600160f81b031916908160001a90535060049490941c936106ec81610a27565b905061067e565b5083156102a75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610278565b6000818152600183016020526040812054801561082b576000610766600183610a3e565b855490915060009061077a90600190610a3e565b90508181146107df57600086600001828154811061079a5761079a6109ae565b90600052602060002001549050808760000184815481106107bd576107bd6109ae565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806107f0576107f0610a55565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506101dc565b60009150506101dc565b60006020828403121561084757600080fd5b81356001600160e01b0319811681146102a757600080fd5b60006020828403121561087157600080fd5b5035919050565b6000806040838503121561088b57600080fd5b8235915060208301356001600160a01b03811681146108a957600080fd5b809150509250929050565b600080604083850312156108c757600080fd5b50508035926020909101359150565b60005b838110156108f15781810151838201526020016108d9565b83811115610900576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161093e8160178501602088016108d6565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161096f8160288401602088016108d6565b01602801949350505050565b602081526000825180602084015261099a8160408501602087016108d6565b601f01601f19169190910160400192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156109f4576109f46109c4565b500290565b60008219821115610a0c57610a0c6109c4565b500190565b634e487b7160e01b600052604160045260246000fd5b600081610a3657610a366109c4565b506000190190565b600082821015610a5057610a506109c4565b500390565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201eaf2a559b6354216b71737aa56d5cd28acb397e1c9e8a4913fd99e9f7c766c064736f6c634300080e0033000000000000000000000000a4709ae4972d014bb0aa87965812ab97481fd447000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063a2c9409911610066578063a2c94099146100f5578063d55ec69714610108578063e4bfdcdc1461011b578063f2fde38b1461012e578063fc0c546a1461014157600080fd5b8063715018a614610098578063799f99bc146100a25780638119c065146100b55780638da5cb5b146100e4575b600080fd5b6100a0610154565b005b6100a06100b036600461042c565b610168565b6004546100c8906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6000546001600160a01b03166100c8565b6001546100c8906001600160a01b031681565b6003546100c8906001600160a01b031681565b6100a0610129366004610477565b61020e565b6100a061013c366004610477565b6102d5565b6002546100c8906001600160a01b031681565b61015c610353565b61016660006103ad565b565b610170610353565b8282600260009054906101000a90046001600160a01b0316836101f4604051610198906103fd565b6001600160a01b03958616815293851660208501529184166040840152909216606082015262ffffff909116608082015260a001604051809103906000f0801580156101e8573d6000803e3d6000fd5b50600480546001600160a01b0319166001600160a01b0392909216919091179055505050565b610216610353565b60025460405182916001600160a01b0316906102319061040a565b6001600160a01b03928316815291166020820152604001604051809103906000f080158015610264573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b0392909216918217905560405163f2fde38b60e01b815233600482015263f2fde38b90602401600060405180830381600087803b1580156102ba57600080fd5b505af11580156102ce573d6000803e3d6000fd5b5050505050565b6102dd610353565b6001600160a01b0381166103475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610350816103ad565b50565b6000546001600160a01b031633146101665760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161033e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6116558061049c83390190565b61092980611af183390190565b6001600160a01b038116811461035057600080fd5b60008060006060848603121561044157600080fd5b833561044c81610417565b9250602084013561045c81610417565b9150604084013561046c81610417565b809150509250925092565b60006020828403121561048957600080fd5b813561049481610417565b939250505056fe60806040526004805463ffffffff60b81b19166205000560b81b1790553480156200002957600080fd5b5060405162001655380380620016558339810160408190526200004c916200012e565b6200005733620000c5565b600180546001600160a01b039687166001600160a01b03199182161790915560038054958716958216959095179094556004805460028054948816949096169390931790945562ffffff16600160a01b026001600160b81b03199091169190931617919091179055620001b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200012b57600080fd5b50565b600080600080600060a086880312156200014757600080fd5b8551620001548162000115565b6020870151909550620001678162000115565b60408701519094506200017a8162000115565b60608701519093506200018d8162000115565b608087015190925062ffffff81168114620001a757600080fd5b809150509295509295909350565b61149080620001c56000396000f3fe6080604052600436106101145760003560e01c80638da5cb5b116100a0578063c31c9c0711610064578063c31c9c071461031a578063d21220a71461033a578063deae729e1461035a578063f2fde38b1461037a578063f41167921461039a57600080fd5b80638da5cb5b1461027a578063ab37fbb714610298578063acb2ad6f146102b8578063b44cb06f146102da578063bdd3d825146102fa57600080fd5b80635249961b116100e75780635249961b146101e357806359966cfd14610205578063715018a61461022557806373dd250c1461023a57806383ce916a1461025a57600080fd5b8063089fe6aa146101195780630dfe1681146101555780633e032a3b1461018d57806349cdeeb9146101c2575b600080fd5b34801561012557600080fd5b5060045461013c90600160a01b900462ffffff1681565b60405162ffffff90911681526020015b60405180910390f35b34801561016157600080fd5b50600354610175906001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b34801561019957600080fd5b506004546101af90600160c81b900461ffff1681565b60405161ffff909116815260200161014c565b6101d56101d03660046110fd565b6103cf565b60405190815260200161014c565b3480156101ef57600080fd5b506102036101fe366004611134565b610556565b005b34801561021157600080fd5b50610203610220366004611161565b610580565b34801561023157600080fd5b506102036105aa565b34801561024657600080fd5b5061020361025536600461117e565b6105be565b34801561026657600080fd5b506101d56102753660046111a3565b6105ea565b34801561028657600080fd5b506000546001600160a01b0316610175565b3480156102a457600080fd5b506102036102b3366004611161565b6107d6565b3480156102c457600080fd5b506004546101af90600160b81b900461ffff1681565b3480156102e657600080fd5b506102036102f53660046111bc565b610800565b34801561030657600080fd5b50600254610175906001600160a01b031681565b34801561032657600080fd5b50600154610175906001600160a01b031681565b34801561034657600080fd5b50600454610175906001600160a01b031681565b34801561036657600080fd5b50610203610375366004611134565b610836565b34801561038657600080fd5b50610203610395366004611134565b610860565b3480156103a657600080fd5b506103ba6103b53660046111a3565b6108de565b6040805192835260208301919091520161014c565b6004546000908190600160c81b900461ffff166103ee6103e885611221565b6103f89190611243565b6104029084611262565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561045457600080fd5b505af1158015610468573d6000803e3d6000fd5b505060035460015461048b94506001600160a01b03918216935016905086610aa9565b60408051610100810182526003546001600160a01b039081168252600480548083166020850152600160a01b900462ffffff168385015233606084015242608084015260a0830188905260c08301859052600060e0840152600154935163414bf38960e01b815292939091169163414bf3899161050a91859101611279565b6020604051808303816000875af1158015610529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054d91906112f6565b95945050505050565b61055e610ba9565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b610588610ba9565b6004805461ffff909216600160b81b0261ffff60b81b19909216919091179055565b6105b2610ba9565b6105bc6000610c03565b565b6105c6610ba9565b6004805462ffffff909216600160a01b0262ffffff60a01b19909216919091179055565b600080600260009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610664919061131f565b50505050505090506000600260009054906101000a90046001600160a01b03166001600160a01b0316631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e591906113c3565b6004546003549192506000916001600160a01b039182169116101561070c57506000610710565b5060015b600454600160c81b900461ffff1661072a6103e887611221565b6107349190611243565b60045461074d90600160a01b900462ffffff1687611221565b600454600160b81b900461ffff16610766606489611221565b6107709190611243565b61077a91906113ec565b61078491906113ec565b61078e90866113ec565b9450600061079f8484888515610c53565b90506000826107bc576107b58583866000610caf565b90506107cc565b6107c98583866000610d66565b90505b9695505050505050565b6107de610ba9565b6004805461ffff909216600160c81b0261ffff60c81b19909216919091179055565b610808610ba9565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b61083e610ba9565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610868610ba9565b6001600160a01b0381166108d25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6108db81610c03565b50565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015610936573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095a919061131f565b50505050505090506000600260009054906101000a90046001600160a01b03166001600160a01b0316631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109db91906113c3565b6004546003549192506000916001600160a01b0391821691161015610a0257506000610a06565b5060015b6000610a158484898515610dd1565b905060008215610a3357610a2c8583866000610caf565b9050610a43565b610a408583866000610d66565b90505b600454610a5c90600160a01b900462ffffff1682611221565b610a669082611262565b600454909150600090600160b81b900461ffff16610a85606484611221565b610a8f9190611243565b610a999083611262565b9199919850909650505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151600092839290871691610b059190611404565b6000604051808303816000865af19150503d8060008114610b42576040519150601f19603f3d011682016040523d82523d6000602084013e610b47565b606091505b5091509150818015610b71575080511580610b71575080806020019051810190610b71919061143f565b610ba25760405162461bcd60e51b8152602060048201526002602482015261534160f01b60448201526064016108c9565b5050505050565b6000546001600160a01b031633146105bc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080856001600160a01b031611610c6a57600080fd5b6000846001600160801b031611610c8057600080fd5b81610c9757610c928585856000610e19565b610ca4565b610ca48585856000610f16565b90505b949350505050565b6000836001600160a01b0316856001600160a01b03161115610ccf579293925b600160601b600160e01b03606084901b166001600160a01b038686038116908716610cf957600080fd5b83610d2f57866001600160a01b0316610d1c8383896001600160a01b0316610fef565b81610d2957610d296111f5565b04610d5b565b610d5b610d468383896001600160a01b03166110a2565b886001600160a01b0316808204910615150190565b979650505050505050565b6000836001600160a01b0316856001600160a01b03161115610d86579293925b81610dae57610c92836001600160801b03168686036001600160a01b0316600160601b610fef565b610ca4836001600160801b03168686036001600160a01b0316600160601b6110a2565b600080856001600160a01b031611610de857600080fd5b6000846001600160801b031611610dfe57600080fd5b81610e1057610c928585856001610f16565b610ca485858560015b600082600003610e2a575083610ca7565b600160601b600160e01b03606085901b168215610ec4576001600160a01b03861684810290858281610e5e57610e5e6111f5565b0403610e8e57818101828110610e8c57610e8283896001600160a01b0316836110a2565b9350505050610ca7565b505b50610ebc8185610ea76001600160a01b038a1683611221565b610eb191906113ec565b808204910615150190565b915050610ca7565b6001600160a01b03861684810290858281610ee157610ee16111f5565b04148015610eee57508082115b610ef757600080fd5b808203610e82610f11846001600160a01b038b16846110a2565b6110e2565b60008115610f7b5760006001600160a01b03841115610f4c57610f4784600160601b876001600160801b0316610fef565b610f63565b610f636001600160801b038616606086901b611221565b9050610ebc610f11826001600160a01b0389166113ec565b60006001600160a01b03841115610fa957610fa484600160601b876001600160801b03166110a2565b610fc6565b610fc6606085901b6001600160801b038716808204910615150190565b905080866001600160a01b031611610fdd57600080fd5b6001600160a01b038616039050610ca7565b6000808060001985870985870292508281108382030391505080600003611028576000841161101d57600080fd5b50829004905061109b565b80841161103457600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60006110af848484610fef565b9050600082806110c1576110c16111f5565b848609111561109b5760001981106110d857600080fd5b6001019392505050565b806001600160a01b03811681146110f857600080fd5b919050565b6000806040838503121561111057600080fd5b50508035926020909101359150565b6001600160a01b03811681146108db57600080fd5b60006020828403121561114657600080fd5b813561109b8161111f565b61ffff811681146108db57600080fd5b60006020828403121561117357600080fd5b813561109b81611151565b60006020828403121561119057600080fd5b813562ffffff8116811461109b57600080fd5b6000602082840312156111b557600080fd5b5035919050565b600080604083850312156111cf57600080fd5b82356111da8161111f565b915060208301356111ea8161111f565b809150509250929050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261123e57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561125d5761125d61120b565b500290565b6000828210156112745761127461120b565b500390565b60006101008201905060018060a01b0380845116835280602085015116602084015262ffffff6040850151166040840152806060850151166060840152506080830151608083015260a083015160a083015260c083015160c083015260e08301516112ef60e08401826001600160a01b03169052565b5092915050565b60006020828403121561130857600080fd5b5051919050565b805180151581146110f857600080fd5b600080600080600080600060e0888a03121561133a57600080fd5b87516113458161111f565b8097505060208801518060020b811461135d57600080fd5b604089015190965061136e81611151565b606089015190955061137f81611151565b608089015190945061139081611151565b60a089015190935060ff811681146113a757600080fd5b91506113b560c0890161130f565b905092959891949750929550565b6000602082840312156113d557600080fd5b81516001600160801b038116811461109b57600080fd5b600082198211156113ff576113ff61120b565b500190565b6000825160005b81811015611425576020818601810151858301520161140b565b81811115611434576000828501525b509190910192915050565b60006020828403121561145157600080fd5b61109b8261130f56fea264697066735822122007790787babb7848758c81e19044e8a682e61e8edf809970e0eb58b35c34435a64736f6c634300080e0033608060405234801561001057600080fd5b5060405161092938038061092983398101604081905261002f916100e4565b61003833610078565b600280546001600160a01b038085166001600160a01b031992831617909255600380549284169290911691909117905561007142600455565b5050610117565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146100df57600080fd5b919050565b600080604083850312156100f757600080fd5b610100836100c8565b915061010e602084016100c8565b90509250929050565b610803806101266000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100cd578063b9166076146100e8578063d8270dce1461011b578063f2fde38b1461012457600080fd5b80633d0b1e2c1461008d5780636febc51814610097578063715018a6146100b257806389476069146100ba575b600080fd5b610095610137565b005b61009f610413565b6040519081526020015b60405180910390f35b6100956104a5565b6100956100c83660046106fa565b6104b9565b6000546040516001600160a01b0390911681526020016100a9565b61010b6100f63660046106fa565b60016020526000908152604090205460ff1681565b60405190151581526020016100a9565b61009f60045481565b6100956101323660046106fa565b6105bf565b6004546101479062127500610739565b42106101aa5760405162461bcd60e51b815260206004820152602760248201527f546f6b656e732075706772616465206973206e6f7420617661696c61626c6520604482015266616e796d6f726560c81b60648201526084015b60405180910390fd5b60006101b4610413565b9050600081116101fe5760405162461bcd60e51b81526020600482015260156024820152744e6f207570677261646561626c6520746f6b656e7360581b60448201526064016101a1565b6002546040516370a0823160e01b815233600482018190526001600160a01b03909216916323b872dd91309084906370a0823190602401602060405180830381865afa158015610252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102769190610751565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156102ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ee919061076a565b61033a5760405162461bcd60e51b815260206004820152601960248201527f4f6c6420746f6b656e207472616e73666572206661696c65640000000000000060448201526064016101a1565b60035460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af115801561038b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103af919061076a565b6103f35760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b60448201526064016101a1565b50336000908152600160208190526040909120805460ff19169091179055565b6002546040516370a0823160e01b815233600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610460573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104849190610751565b9050600061049e610496836004610638565b6103e8610644565b9392505050565b6104ad610650565b6104b760006106aa565b565b6104c1610650565b806001600160a01b03811663a9059cbb6104e36000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b9190610751565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ba919061076a565b505050565b6105c7610650565b6001600160a01b03811661062c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016101a1565b610635816106aa565b50565b600061049e828461078c565b600061049e82846107ab565b6000546001600160a01b031633146104b75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561070c57600080fd5b81356001600160a01b038116811461049e57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561074c5761074c610723565b500190565b60006020828403121561076357600080fd5b5051919050565b60006020828403121561077c57600080fd5b8151801515811461049e57600080fd5b60008160001904831182151516156107a6576107a6610723565b500290565b6000826107c857634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220ecd9efbd613b33b8e7f8a6f5ee8c093e0d7ca96f4d7335906eaaaaa316099be464736f6c634300080e0033a2646970667358221220247e53c2e975dfad108835fd9d9c839821da9065e554ab88b6face52b2775e3f64736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a4709ae4972d014bb0aa87965812ab97481fd447000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
-----Decoded View---------------
Arg [0] : _tokenFeeWallet (address): 0xa4709Ae4972d014bB0aA87965812ab97481Fd447
Arg [1] : _weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a4709ae4972d014bb0aa87965812ab97481fd447
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.