Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Arrakis
Overview
Max Total Supply
0 ARRAKIS
Holders
1
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 ARRAKISLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
PrivateVaultNFT
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {INFTSVG, SVGParams} from "src/utils/NFTSVG.sol"; import {IPrivateVaultNFT} from "./interfaces/IPrivateVaultNFT.sol"; import {IArrakisMetaVault} from "./interfaces/IArrakisMetaVault.sol"; import {IRenderController} from "./interfaces/IRenderController.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {RenderController} from "./RenderController.sol"; import {Ownable} from "@solady/contracts/auth/Ownable.sol"; contract PrivateVaultNFT is Ownable, ERC721, IPrivateVaultNFT { address public immutable renderController; constructor() ERC721("Arrakis Private LP NFT", "ARRAKIS") { _initializeOwner(msg.sender); renderController = address(new RenderController()); } /// @notice function used to mint nft (representing a vault) and send it. /// @param to_ address where to send the NFT. /// @param tokenId_ id of the NFT to mint. function mint(address to_, uint256 tokenId_) external onlyOwner { _safeMint(to_, tokenId_); } function tokenURI(uint256 tokenId_) public view override returns (string memory) { IArrakisMetaVault vault = IArrakisMetaVault(address(uint160(tokenId_))); (uint256 amount0, uint256 amount1) = vault.totalUnderlying(); address _renderer = IRenderController(renderController).renderer(); try this.getMetaDatas(vault.token0(), vault.token1()) returns ( uint8 decimals0, uint8 decimals1, string memory symbol0, string memory symbol1 ) { return INFTSVG(_renderer).generateVaultURI( SVGParams({ vault: address(vault), amount0: amount0, amount1: amount1, decimals0: decimals0, decimals1: decimals1, symbol0: symbol0, symbol1: symbol1 }) ); } catch { return INFTSVG(_renderer).generateFallbackURI( SVGParams({ vault: address(vault), amount0: amount0, amount1: amount1, decimals0: 4, decimals1: 4, symbol0: "TKN0", symbol1: "TKN1" }) ); } } function getMetaDatas( address token0_, address token1_ ) public view returns ( uint8 decimals0, uint8 decimals1, string memory symbol0, string memory symbol1 ) { decimals0 = IERC20Metadata(token0_).decimals(); decimals1 = IERC20Metadata(token1_).decimals(); symbol0 = IERC20Metadata(token0_).symbol(); symbol1 = IERC20Metadata(token1_).symbol(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "@solady/contracts/utils/Base64.sol"; import {NFTSVGUtils} from "./NFTSVGUtils.sol"; /// @notice Parameters for generating the URI struct SVGParams { address vault; uint256 amount0; uint256 amount1; uint8 decimals0; uint8 decimals1; string symbol0; string symbol1; } /// @dev Interface for the NFTSVG contract interface INFTSVG { /// @notice Checks if the contract is compliant with the NFTSVG interface function isNFTSVG() external pure returns (bool); /// @notice Generates a URI for a given vault /// @param params_ Parameters for generating the URI function generateVaultURI(SVGParams memory params_) external pure returns (string memory); /// @notice Generates a fallback URI for a given vault /// @param params_ Parameters for generating the URI function generateFallbackURI(SVGParams memory params_) external pure returns (string memory); } contract NFTSVG is INFTSVG { /// @notice Checks if the contract is compliant with the NFTSVG interface function isNFTSVG() external pure returns (bool) { return true; } /// @notice Generates a URI for a given vault /// @param params_ Parameters for generating the URI function generateVaultURI(SVGParams memory params_) public pure returns (string memory) { string memory name = _generateName(params_); string memory description = _generateDescription(params_); string memory image = Base64.encode(bytes(_generateSVGImage(params_.vault))); return string( abi.encodePacked( "data:application/json;base64,", Base64.encode( bytes( abi.encodePacked( '{"name":"', name, '", "description":"', description, '", "image": "', "data:image/svg+xml;base64,", image, '"}' ) ) ) ) ); } /// @notice Generates a fallback URI for a given vault /// @param params_ Parameters for generating the URI function generateFallbackURI(SVGParams memory params_) public pure returns (string memory) { string memory description = _generateDescription(params_); string memory image = Base64.encode(bytes(_generateSVGImage(params_.vault))); return string( abi.encodePacked( "data:application/json;base64,", Base64.encode( bytes( abi.encodePacked( '{"name":" Arrakis Private Vault', '", "description":"', description, '", "image": "', "data:image/svg+xml;base64,", image, '"}' ) ) ) ) ); } /// @notice Generates the name of the URI for a given vault /// @param params_ Parameters for generating the URI function _generateName(SVGParams memory params_) internal pure returns (string memory) { (string memory s1, string memory s2) = NFTSVGUtils.addressToString(params_.vault); return string( abi.encodePacked( "Arrakis ", params_.symbol0, "/", params_.symbol1, ": ", s1, s2 ) ); } /// @notice Generates the description of the URI for a given vault /// @param params_ Parameters for generating the URI function _generateDescription(SVGParams memory params_) internal pure returns (string memory) { (string memory s1, string memory s2) = NFTSVGUtils.addressToString(params_.vault); return string( abi.encodePacked( unicode"⚠️ DO NOT TRANSFER TO UNTRUSTED PARTIES.", "\\n\\nThis NFT gives ownership of an Arrakis Modular Private Vault (", s1, s2, ") with an inventory of ", NFTSVGUtils.uintToFloatString( params_.amount0, params_.decimals0 ), " ", params_.symbol0, " and ", NFTSVGUtils.uintToFloatString( params_.amount1, params_.decimals1 ), " ", params_.symbol1, "." ) ); } /// @notice Generates the SVG image of the URI for a given vault /// @param vault_ The vault address represented by the NFT function _generateSVGImage(address vault_) internal pure returns (string memory svg) { return string( abi.encodePacked( '<svg width="290" height="500" viewBox="0 0 290 500" fill="none" xmlns="http://www.w3.org/2000/svg"><defs>', _generateSVGDefs(), "</defs>", _generateSVGFrame(), _generateSVGFront(), _generateSVGBack(vault_), "</svg>" ) ); } // #region auxiliary functions for generating the SVG image function _generateSVGDefs() internal pure returns (string memory) { return string( abi.encodePacked( '<linearGradient id="rect-gradient" gradientUnits="objectBoundingBox" x1="0" y1="0" x2=".75" y2="1.5">', '<stop offset="0"><animate attributeName="stop-color" values="#050302;#050302;#7D440E;#7D440E;#DC701D;#F0B567;#F0B567;#7D440E;#7D440E;#050302;#050302;#050302;#050302;" dur="30s" repeatCount="indefinite"></animate></stop>', '<stop offset=".33"><animate attributeName="stop-color" values="#050302;#050302;#7D440E;#F0B567;#F0B567;#EC9117;#DC701D;#FA7C40;#7D440E;#7D440E;#050302;#050302;#050302;" dur="30s" repeatCount="indefinite"></animate></stop>', '<stop offset=".67"><animate attributeName="stop-color" values="#050302;#050302;#050302;#7D440E;#DC701D;#F0B567;#F0B567;#EC9117;#DC701D;#7D440E;#E89857;#050302;#050302;" dur="30s" repeatCount="indefinite"></animate></stop>', '<stop offset="1"><animate attributeName="stop-color" values="#050302;#050302;#050302;#050302;#7D440E;#DC701D;#DC701D;#FA7C40;#FA7C40;#DC701D;#E89857;#050302;#050302;" dur="30s" repeatCount="indefinite"></animate></stop>', '<animateTransform attributeName="gradientTransform" type="translate" from="-.8 -.8" to=".8 .8" dur="30s" repeatCount="indefinite" /></linearGradient>', '<linearGradient id="tail-gradient" x1="183.99" y1="59.2903" x2="171.409" y2="178.815" gradientUnits="userSpaceOnUse"><stop stop-color="white"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient>', _generateSVGMasks() ) ); } function _generateSVGMasks() internal pure returns (string memory) { return string( abi.encodePacked( '<mask id="waves-mask"><rect x="0" y="0" width="100%" height="100%" fill="white" />', '<g style="scale(3)"><linearGradient id="waves2" x1="0" x2="1" y1="0" y2="0"><stop stop-color="#000000" offset="0"></stop><stop stop-color="#000000" offset="1"></stop></linearGradient>', '<path d="" fill="black" opacity="0.33"><animate attributeName="d" dur="8s" repeatCount="indefinite" keyTimes="0;0.333;0.667;1" calcMode="spline" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" begin="0s" values="M0 0L0 279.72Q72.50 95.90 145 80.31T290 -2.87L290 0Z;M0 0L0 178.34Q72.50 66.44 145 50.16T290 -49.50L290 0Z;M0 0L0 244.09Q72.50 178.37 145 151.37T290 -124.25L290 0Z;M0 0L0 279.72Q72.50 95.90 145 80.31T290 -2.87L290 0Z"></animate></path>' '<path d="" fill="black" opacity="0.33"><animate attributeName="d" dur="8s" repeatCount="indefinite" keyTimes="0;0.333;0.667;1" calcMode="spline" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" begin="-4.166666666666667s" values="M0 0L0 258.07Q72.50 130.78 145 98.80T290 -39.43L290 0Z;M0 0L0 242.23Q72.50 39.39 145 16.94T290 -28.59L290 0Z;M0 0L0 224.02Q72.50 53.87 145 31.25T290 -65.65L290 0Z;M0 0L0 258.07Q72.50 130.78 145 98.80T290 -39.43L290 0Z"></animate></path>', "</g></mask>", '<mask id="inner_rect_mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="10.5" y="10.5" width="269" height="479"><rect x="10.5" y="10.5" width="269" height="479" rx="23.5" fill="#D9D9D9"/></mask>' ) ); } function _generateSVGFrame() internal pure returns (string memory) { return string( abi.encodePacked( '<rect width="290" height="500" rx="24" fill="black"/><rect width="290" height="500" rx="24" fill="url(#rect-gradient)"/>', '<g id="waves" mask="url(#inner_rect_mask)"><g mask="url(#waves-mask)"><g style="transform:translate(145.0px,250.0px) scale(-1,1) translate(-145.0px,-250.0px)"><linearGradient id="waves1" x1="0" x2="1" y1="0" y2="0"><stop stop-color="#ffffff" offset="0"></stop><stop stop-color="#ffffff" offset="1"></stop></linearGradient>', '<path d="" fill="white" opacity="0.033"><animate attributeName="d" dur="15s" repeatCount="indefinite" keyTimes="0;0.333;0.667;1" calcMode="spline" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" begin="0s" values="M0 0L0 225.85Q72.50 535.81 145 487.99T290 618.39L290 0Z;M0 0L0 62.93Q72.50 363.50 145 349.64T290 259.60L290 0Z;M0 0L0 215.10Q72.50 239.83 145 212.50T290 525.33L290 0Z;M0 0L0 225.85Q72.50 535.81 145 487.99T290 618.39L290 0Z"></animate></path>', '<path d="" fill="white" opacity="0.033"><animate attributeName="d" dur="15s" repeatCount="indefinite" keyTimes="0;0.333;0.667;1" calcMode="spline" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" begin="-3.7037037037037037s" values="M0 0L0 -139.57Q72.50 522.50 145 485.95T290 463.92L290 0Z;M0 0L0 206.11Q72.50 251.85 145 229.63T290 357.17L290 0Z;M0 0L0 -112.70Q72.50 427.35 145 404.61T290 683.65L290 0Z;M0 0L0 -139.57Q72.50 522.50 145 485.95T290 463.92L290 0Z"></animate></path>', '<path d="" fill="white" opacity="0.033"><animate attributeName="d" dur="15s" repeatCount="indefinite" keyTimes="0;0.333;0.667;1" calcMode="spline" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" begin="-7.407407407407407s" values="M0 0L0 120.25Q72.50 269.55 145 248.41T290 380.02L290 0Z;M0 0L0 -35.24Q72.50 502.96 145 476.67T290 570.38L290 0Z;M0 0L0 -1.04Q72.50 515.48 145 487.93T290 370.53L290 0Z;M0 0L0 120.25Q72.50 269.55 145 248.41T290 380.02L290 0Z"></animate></path>', '</g></g></g><rect x="10.5" y="10.5" width="269" height="479" rx="23.5" stroke="white" stroke-opacity="0.33" stroke-width="2"/>', NFTSVGUtils.generateSVGLogo(), _generateSVGDunes() ) ); } function _generateSVGDunes() internal pure returns (string memory) { return string( abi.encodePacked( '<g id="dunes" transform="translate(0 33)"><g mask="url(#inner_rect_mask)">', '<path d="M0.5 355.5C178.5 330.5 153.023 310.248 108 316C76.5 320.024 86.3739 305.5 106 294.5C135.856 277.767 137.872 272.876 130.5 267.5M130.5 267.5C73.5966 287.906 40.9646 300.008 0.5 305.5M130.5 267.5C169.496 271.232 185.689 274.308 210.5 280.5C249.139 288.743 267.721 291.842 290 292" stroke="white" stroke-opacity="0.33"/>', '<path d="M0.5 262.5C0.5 262.5 48.5 255 102 253C155.5 251 183 241.5 189.5 235.227M189.5 235.227C222.621 246.569 191.696 261.647 163.5 271M189.5 235.227C198.96 233.427 225.5 242.827 244.5 246.329C273.228 251.623 280.179 251.674 291 251.263" stroke="white" stroke-opacity="0.33"/>', "</g></g>" ) ); } function _generateSVGFront() internal pure returns (string memory) { return string( abi.encodePacked( '<g id="front" fill="white">', '<animate attributeName="opacity" values="1;1;1;1;1;1;1;1;0;0;0;0;0;1" dur="30s" repeatCount="indefinite"/>', '<path d="M171.691 152.953L134.814 127.595L114.918 136.159C114.776 136.241 114.61 136.274 114.447 136.253C114.284 136.231 114.133 136.157 114.017 136.041C113.901 135.924 113.826 135.773 113.805 135.61C113.783 135.447 113.816 135.282 113.899 135.139L122.189 115.243L113.899 95.3515C113.814 95.2091 113.78 95.0429 113.8 94.8788C113.821 94.7146 113.895 94.562 114.012 94.4448C114.129 94.3276 114.281 94.2525 114.445 94.2313C114.609 94.2101 114.775 94.244 114.918 94.3276L134.814 102.631L154.706 94.3276C154.849 94.246 155.015 94.2137 155.178 94.2356C155.341 94.2575 155.492 94.3324 155.609 94.4488C155.725 94.5651 155.8 94.7165 155.822 94.8796C155.844 95.0427 155.811 95.2085 155.73 95.3515L147.439 115.243L172.524 152.146C172.631 152.257 172.69 152.405 172.687 152.559C172.685 152.713 172.621 152.859 172.511 152.966C172.401 153.073 172.252 153.132 172.098 153.129C171.944 153.127 171.798 153.064 171.691 152.953Z"/>', '<g id="sand-worm">', '<path opacity="0.6" d="M142.289 53.0082C140.09 52.9128 136.103 53.6677 133.283 54.2794C133.064 54.3278 132.866 54.445 132.718 54.6138C132.57 54.7826 132.479 54.9942 132.46 55.2178C132.441 55.4415 132.493 55.6655 132.61 55.8572C132.727 56.0489 132.902 56.1983 133.109 56.2837L135.578 57.2989C135.578 57.2989 139.023 55.3423 142.289 53.0082Z"/>', '<path opacity="0.6" d="M135.257 65.8977C137.673 65.9238 140.866 65.8977 142.727 65.7546C140.155 64.453 136.389 62.7654 136.389 62.7654L134.653 63.9801C134.47 64.1087 134.332 64.2923 134.26 64.5044C134.188 64.7165 134.186 64.9461 134.253 65.1598C134.32 65.3734 134.454 65.5602 134.634 65.6929C134.814 65.8256 135.033 65.8973 135.257 65.8977Z"/>', '<path d="M211.14 112.992C207.492 82.4446 182.151 57.377 151.977 53.7805C147.539 53.2512 143.569 53.0646 142.463 53.0082C142.038 52.9841 141.619 53.1067 141.274 53.3553C139.296 54.761 137.152 56.236 135.061 57.6547C134.675 57.9172 134.365 58.276 134.16 58.6956C133.956 59.1152 133.865 59.5809 133.896 60.0466C133.927 60.5123 134.079 60.9618 134.338 61.3504C134.596 61.739 134.952 62.0534 135.369 62.2621C137.773 63.4595 140.293 64.7177 142.003 65.5767C142.309 65.7282 142.651 65.7941 142.992 65.7676C143.46 65.7286 148.91 65.8804 150.571 66.0713C167.925 68.0236 184.168 78.1192 193.565 92.8916C212.355 121.959 202.511 160.216 174.433 178.012C173.973 178.303 173.487 178.598 172.979 178.88C171.292 179.851 172.628 182.428 174.381 181.569C174.958 181.287 175.522 180.992 176.068 180.702C199.908 167.339 214.984 140.636 211.14 112.992Z" fill="url(#tail-gradient)"/>', '<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="360 140 120" to="0 140 120" dur="25s" repeatCount="indefinite"/>', "</g></g>" ) ); } function _generateSVGBack(address vault_) internal pure returns (string memory) { (string memory s1, string memory s2) = NFTSVGUtils.addressToString(vault_); return string( abi.encodePacked( '<g id="back" attributeName="opacity" values="0;" fill="white" font-family="system-ui" font-weight="bold" text-anchor="middle">', '<animate attributeName="opacity" values="0;0;0;0;0;0;0;0;0;1;1;1;0;0" dur="30s" repeatCount="indefinite"/>', '<text font-size="18" x="145" y="75">This NFT gives ownership</text><text font-size="18" x="145" y="100">rights of a private vault</text>', '<g opacity="0.67"><text font-size="13" font-weight="normal" x="145" y="127.5">Be careful when transferring</text>', '<text font-size="13" font-weight="normal" x="145" y="172.5">Vault ID</text>', '</g><text x="145" y="200">', s1, '</text><text x="145" y="222.5">', s2, "</text></g>" ) ); } // #endregion auxiliary functions for generating the SVG image }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IPrivateVaultNFT { /// @notice function used to mint nft (representing a vault) and send it. /// @param to_ address where to send the NFT. /// @param tokenId_ id of the NFT to mint. function mint(address to_, uint256 tokenId_) external; // #region view functions. /// @dev for doing meta data calls of tokens. function getMetaDatas( address token0_, address token1_ ) external view returns ( uint8 decimals0, uint8 decimals1, string memory symbol0, string memory symbol1 ); // #endregion view functions. }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {IArrakisLPModule} from "./IArrakisLPModule.sol"; /// @title IArrakisMetaVault /// @notice IArrakisMetaVault is a vault that is able to invest dynamically deposited /// tokens into protocols through his module. interface IArrakisMetaVault { // #region errors. /// @dev triggered when an address that should not /// be zero is equal to address zero. error AddressZero(string property); /// @dev triggered when the caller is different than /// the manager. error OnlyManager(address caller, address manager); /// @dev triggered when a low level call failed during /// execution. error CallFailed(); /// @dev triggered when manager try to set the active /// module as active. error SameModule(); /// @dev triggered when owner of the vault try to set the /// manager with the current manager. error SameManager(); /// @dev triggered when all tokens withdrawal has been done /// during a switch of module. error ModuleNotEmpty(uint256 amount0, uint256 amount1); /// @dev triggered when owner try to whitelist a module /// that has been already whitelisted. error AlreadyWhitelisted(address module); /// @dev triggered when owner try to blacklist a module /// that has not been whitelisted. error NotWhitelistedModule(address module); /// @dev triggered when owner try to blacklist the active module. error ActiveModule(); /// @dev triggered during vault creation if token0 address is greater than /// token1 address. error Token0GtToken1(); /// @dev triggered during vault creation if token0 address is equal to /// token1 address. error Token0EqToken1(); /// @dev triggered when whitelisting action is occuring and module's beacon /// is not whitelisted on module registry. error NotWhitelistedBeacon(); /// @dev triggered when guardian of the whitelisting module is different than /// the guardian of the registry. error NotSameGuardian(); /// @dev triggered when a function logic is not implemented. error NotImplemented(); /// @dev triggered when two arrays suppposed to have the same length, have different length. error ArrayNotSameLength(); /// @dev triggered when function is called by someone else than the owner. error OnlyOwner(); /// @dev triggered when setModule action try to remove funds. error WithdrawNotAllowed(); /// @dev triggered when setModule function end without /// initiliazePosition call. error PositionNotInitialized(); /// @dev triggered when the first external call of setModule function /// isn't InitializePosition function. error NotPositionInitializationCall(); // #endregion errors. // #region events. /// @notice Event describing a manager fee withdrawal. /// @param amount0 amount of token0 that manager has earned and will be transfered. /// @param amount1 amount of token1 that manager has earned and will be transfered. event LogWithdrawManagerBalance(uint256 amount0, uint256 amount1); /// @notice Event describing owner setting the manager. /// @param manager address of manager that will manage the portfolio. event LogSetManager(address manager); /// @notice Event describing manager setting the module. /// @param module address of the new active module. /// @param payloads data payloads for initializing positions on the new module. event LogSetModule(address module, bytes[] payloads); /// @notice Event describing default module that the vault will be initialized with. /// @param module address of the default module. event LogSetFirstModule(address module); /// @notice Event describing list of modules that has been whitelisted by owner. /// @param modules list of addresses corresponding to new modules now available /// to be activated by manager. event LogWhiteListedModules(address[] modules); /// @notice Event describing whitelisted of the first module during vault creation. /// @param module default activation. event LogWhitelistedModule(address module); /// @notice Event describing blacklisting action of modules by owner. /// @param modules list of addresses corresponding to old modules that has been /// blacklisted. event LogBlackListedModules(address[] modules); // #endregion events. /// @notice function used to initialize default module. /// @param module_ address of the default module. function initialize(address module_) external; /// @notice function used to set module /// @param module_ address of the new module /// @param payloads_ datas to initialize/rebalance on the new module function setModule( address module_, bytes[] calldata payloads_ ) external; /// @notice function used to whitelist modules that can used by manager. /// @param beacons_ array of beacons addresses to use for modules creation. /// @param data_ array of payload to use for modules creation. function whitelistModules( address[] calldata beacons_, bytes[] calldata data_ ) external; /// @notice function used to blacklist modules that can used by manager. /// @param modules_ array of module addresses to be blacklisted. function blacklistModules(address[] calldata modules_) external; // #region view functions. /// @notice function used to get the list of modules whitelisted. /// @return modules whitelisted modules addresses. function whitelistedModules() external view returns (address[] memory modules); /// @notice function used to get the amount of token0 and token1 sitting /// on the position. /// @return amount0 the amount of token0 sitting on the position. /// @return amount1 the amount of token1 sitting on the position. function totalUnderlying() external view returns (uint256 amount0, uint256 amount1); /// @notice function used to get the amounts of token0 and token1 sitting /// on the position for a specific price. /// @param priceX96 price at which we want to simulate our tokens composition /// @return amount0 the amount of token0 sitting on the position for priceX96. /// @return amount1 the amount of token1 sitting on the position for priceX96. function totalUnderlyingAtPrice(uint160 priceX96) external view returns (uint256 amount0, uint256 amount1); /// @notice function used to get the initial amounts needed to open a position. /// @return init0 the amount of token0 needed to open a position. /// @return init1 the amount of token1 needed to open a position. function getInits() external view returns (uint256 init0, uint256 init1); /// @notice function used to get the address of token0. function token0() external view returns (address); /// @notice function used to get the address of token1. function token1() external view returns (address); /// @notice function used to get manager address. function manager() external view returns (address); /// @notice function used to get module used to /// open/close/manager a position. function module() external view returns (IArrakisLPModule); /// @notice function used to get module registry. /// @return registry address of module registry. function moduleRegistry() external view returns (address registry); // #endregion view functions. }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IRenderController { // #region errors. error InvalidRenderer(); error AddressZero(); // #endregion errors. event LogSetRenderer(address newRenderer); // #region functions. /// @notice function used to set the renderer contract adress /// @dev only the owner can do it. /// @param renderer_ address of the contract that will /// render the tokenUri for the svg of the nft. function setRenderer(address renderer_) external; // #endregion functions. // #region view functions. /// @dev for knowning if renderer is a NFTSVG contract. function isNFTSVG(address renderer_) external view returns (bool); /// @notice NFTSVG contract that will generate the tokenURI. function renderer() external view returns (address); // #endregion view functions. }
// 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.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {INFTSVG} from "src/utils/NFTSVG.sol"; import {IRenderController} from "./interfaces/IRenderController.sol"; import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import {Ownable} from "@solady/contracts/auth/Ownable.sol"; contract RenderController is Ownable, IRenderController, Initializable { address public renderer; function initialize(address owner_) external initializer { if (owner_ == address(0)) { revert AddressZero(); } _initializeOwner(owner_); } /// @notice function used to set the renderer contract /// @dev only the svgController can do it. /// @param renderer_ address of the contract that will /// render the tokenUri for the svg of the nft. function setRenderer(address renderer_) external onlyOwner { bool _isNftSvg; try this.isNFTSVG(renderer_) returns (bool isNs) { _isNftSvg = isNs; } catch { _isNftSvg = false; } if (!_isNftSvg) revert InvalidRenderer(); renderer = renderer_; emit LogSetRenderer(renderer_); } function isNFTSVG(address renderer_) public view returns (bool) { return INFTSVG(renderer_).isNFTSVG(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library to encode strings in Base64. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol) /// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>. library Base64 { /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// See: https://datatracker.ietf.org/doc/html/rfc4648 /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'. /// @param noPadding Whether to strip away the padding. function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { // Multiply by 4/3 rounded up. // The `shl(2, ...)` is equivalent to multiplying by 4. let encodedLength := shl(2, div(add(dataLength, 2), 3)) // Set `result` to point to the start of the free memory. result := mload(0x40) // Store the table into the scratch space. // Offsetted by -1 byte so that the `mload` will load the character. // We will rewrite the free memory pointer at `0x40` later with // the allocated size. // The magic constant 0x0670 will turn "-_" into "+/". mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") mstore(0x3f, xor("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0670))) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, encodedLength) // Run over the input, 3 bytes at a time. for {} 1 {} { data := add(data, 3) // Advance 3 bytes. let input := mload(data) // Write 4 bytes. Optimized for fewer stack operations. mstore8(0, mload(and(shr(18, input), 0x3F))) mstore8(1, mload(and(shr(12, input), 0x3F))) mstore8(2, mload(and(shr(6, input), 0x3F))) mstore8(3, mload(and(input, 0x3F))) mstore(ptr, mload(0x00)) ptr := add(ptr, 4) // Advance 4 bytes. if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. // Equivalent to `o = [0, 2, 1][dataLength % 3]`. let o := div(2, mod(dataLength, 3)) // Offset `ptr` and pad with '='. We can simply write over the end. mstore(sub(ptr, o), shl(240, 0x3d3d)) // Set `o` to zero if there is padding. o := mul(iszero(iszero(noPadding)), o) mstore(sub(ptr, o), 0) // Zeroize the slot after the string. mstore(result, sub(encodedLength, o)) // Store the length. } } } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, false, false)`. function encode(bytes memory data) internal pure returns (string memory result) { result = encode(data, false, false); } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, fileSafe, false)`. function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) { result = encode(data, fileSafe, false); } /// @dev Decodes base64 encoded `data`. /// /// Supports: /// - RFC 4648 (both standard and file-safe mode). /// - RFC 3501 (63: ','). /// /// Does not support: /// - Line breaks. /// /// Note: For performance reasons, /// this function will NOT revert on invalid `data` inputs. /// Outputs for invalid inputs will simply be undefined behaviour. /// It is the user's responsibility to ensure that the `data` /// is a valid base64 encoded string. function decode(string memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { let decodedLength := mul(shr(2, dataLength), 3) for {} 1 {} { // If padded. if iszero(and(dataLength, 3)) { let t := xor(mload(add(data, dataLength)), 0x3d3d) // forgefmt: disable-next-item decodedLength := sub( decodedLength, add(iszero(byte(30, t)), iszero(byte(31, t))) ) break } // If non-padded. decodedLength := add(decodedLength, sub(and(dataLength, 3), 1)) break } result := mload(0x40) // Write the length of the bytes. mstore(result, decodedLength) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, decodedLength) // Load the table into the scratch space. // Constants are optimized for smaller bytecode with zero gas overhead. // `m` also doubles as the mask of the upper 6 bits. let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc mstore(0x5b, m) mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064) mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4) for {} 1 {} { // Read 4 bytes. data := add(data, 4) let input := mload(data) // Write 3 bytes. // forgefmt: disable-next-item mstore(ptr, or( and(m, mload(byte(28, input))), shr(6, or( and(m, mload(byte(29, input))), shr(6, or( and(m, mload(byte(30, input))), shr(6, mload(byte(31, input))) )) )) )) ptr := add(ptr, 3) if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. mstore(end, 0) // Zeroize the slot after the bytes. mstore(0x60, 0) // Restore the zero slot. } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; library NFTSVGUtils { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; /// @notice Generates the logo for the NFT. function generateSVGLogo() public pure returns (string memory) { return string( abi.encodePacked( '<g id="text-logo" fill="white">', '<path d="M79.9663 439.232L57.0249 463.54L57.217 463.934H82.2822V458.758H70.5587L85.4821 442.936V463.934H91.9779V444.152C91.9779 437.754 84.3214 434.62 79.9692 439.232H79.9663Z"/>', '<path d="M225.085 463.928H205.16V458.119H226.554L208.558 449.852L208.307 449.691C205.646 448.006 204.307 445.656 205.18 442.303C206.027 439.045 208.659 437.464 211.729 437.464H231.163V443.281H211.145L227.732 451.178C230.903 452.751 232.598 455.316 231.723 458.804C230.903 462.099 228.327 463.92 225.099 463.92L225.091 463.928H225.085Z"/>', '<path d="M169.585 437.473H163.073V463.929H169.585V437.473Z"/><path d="M193.81 437.464H184.47L172.802 447.1C171.817 447.997 171.213 449.28 171.148 450.631C171.082 452.029 171.594 453.406 172.551 454.415L184.413 463.94H193.911L178.338 450.867L193.81 437.464Z"/>', '<path d="M202.296 437.473H195.783V463.937H202.296V437.473Z"/><path d="M101.976 463.937H95.4628V447.31C95.4628 441.878 99.7896 437.473 105.125 437.473H114.453V443.281H105.266C103.45 443.281 101.976 444.782 101.976 446.631V463.937Z"/>', '<path d="M121.878 463.937H115.366V447.31C115.366 441.878 119.692 437.473 125.027 437.473H134.356V443.281H125.169C123.353 443.281 121.878 444.782 121.878 446.631V463.937Z"/>', '<path d="M147.449 439.232L124.508 463.54L124.7 463.934H149.765V458.758H138.042L152.964 442.936V463.934H159.46V444.152C159.46 437.754 151.804 434.62 147.452 439.232H147.449Z"/>', '</g>' ) ); } /// @notice Converts an address to 2 string slices. /// @param addr_ address to convert to string. function addressToString(address addr_) public pure returns (string memory, string memory) { uint256 value = uint256(uint160(addr_)); bytes memory s1 = new bytes(22); bytes memory s2 = new bytes(20); s1[0] = "0"; s1[1] = "x"; for (uint256 i = 19; i > 0; i--) { s2[i] = HEX_DIGITS[value & 0xf]; value >>= 4; } s2[0] = HEX_DIGITS[value & 0xf]; value >>= 4; for (uint256 i = 21; i > 1; i--) { s1[i] = HEX_DIGITS[value & 0xf]; value >>= 4; } return (string(s1), string(s2)); } /// @notice Converts uints to float strings with 4 decimal places. /// @param value_ uint to convert to string. /// @param decimals_ number of decimal places of the input value. function uintToFloatString( uint256 value_, uint8 decimals_ ) public pure returns (string memory) { if (decimals_ < 5) { return _uintToString(value_); } uint256 scaleFactor = 10 ** decimals_; uint256 fraction = (value_ % scaleFactor) / 10 ** (decimals_ - 4); string memory fractionStr; if (fraction == 0) { fractionStr = "0000"; } else if (fraction < 10) { fractionStr = string( abi.encodePacked("000", _uintToString(fraction)) ); } else if (fraction < 100) { fractionStr = string( abi.encodePacked("00", _uintToString(fraction)) ); } else if (fraction < 1000) { fractionStr = string(abi.encodePacked("0", _uintToString(fraction))); } else { fractionStr = _uintToString(fraction); } return string( abi.encodePacked( _uintToString(value_ / scaleFactor), ".", fractionStr ) ); } /// @notice Code borrowed form: /// https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol /// /// @notice Converts uints to strings. /// @param value_ uint to convert to string. function _uintToString(uint256 value_) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. let newFreeMemoryPointer := add(mload(0x40), 160) // Update the free memory pointer to avoid overriding our string. mstore(0x40, newFreeMemoryPointer) // Assign str to the end of the zone of newly allocated memory. str := sub(newFreeMemoryPointer, 32) // Clean the last word of memory it may not be overwritten. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value_ } 1 {} { // Move the pointer 1 byte to the left. str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing temp until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } // Compute and cache the final total length of the string. let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 32) // Store the string's length at the start of memory allocated for our string. mstore(str, length) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IArrakisMetaVault} from "./IArrakisMetaVault.sol"; import {IOracleWrapper} from "./IOracleWrapper.sol"; /// @title Liquidity providing module interface. /// @author Arrakis Finance /// @notice Module interfaces, modules are implementing differents strategies that an /// arrakis module can use. interface IArrakisLPModule { // #region errors. /// @dev triggered when an address that should not /// be zero is equal to address zero. error AddressZero(); /// @dev triggered when the caller is different than /// the metaVault that own this module. error OnlyMetaVault(address caller, address metaVault); /// @dev triggered when the caller is different than /// the manager defined by the metaVault. error OnlyManager(address caller, address manager); /// @dev triggered if proportion of minting or burning is /// zero. error ProportionZero(); /// @dev triggered if during withdraw more than 100% of the /// position. error ProportionGtBASE(); /// @dev triggered when manager want to set his more /// earned by the position than 100% of fees earned. error NewFeesGtPIPS(uint256 newFees); /// @dev triggered when manager is setting the same fees /// that already active. error SameManagerFee(); /// @dev triggered when inits values are zeros. error InitsAreZeros(); /// @dev triggered when pause/unpaused function is /// called by someone else than guardian. error OnlyGuardian(); // #endregion errors. // #region events. /// @notice Event describing a withdrawal of participation by an user inside this module. /// @dev withdraw action can be indexed by receiver. /// @param receiver address that will receive the tokens withdrawn. /// @param proportion percentage of the current position that user want to withdraw. /// @param amount0 amount of token0 send to "receiver" due to withdraw action. /// @param amount1 amount of token1 send to "receiver" due to withdraw action. event LogWithdraw( address indexed receiver, uint256 proportion, uint256 amount0, uint256 amount1 ); /// @notice Event describing a manager fee withdrawal. /// @param manager address of the manager that will fees earned due to his fund management. /// @param amount0 amount of token0 that manager has earned and will be transfered. /// @param amount1 amount of token1 that manager has earned and will be transfered. event LogWithdrawManagerBalance( address manager, uint256 amount0, uint256 amount1 ); /// @notice Event describing manager set his fees. /// @param oldFee fees share that have been taken by manager. /// @param newFee fees share that have been taken by manager. event LogSetManagerFeePIPS(uint256 oldFee, uint256 newFee); // #endregion events. /// @notice function used to pause the module. /// @dev only callable by guardian function pause() external; /// @notice function used to unpause the module. /// @dev only callable by guardian function unpause() external; /// @notice function used to initialize the module /// when a module switch happen /// @param data_ bytes that contain information to initialize /// the position. function initializePosition(bytes calldata data_) external; /// @notice function used by metaVault to withdraw tokens from the strategy. /// @param receiver_ address that will receive tokens. /// @param proportion_ the proportion of the total position that need to be withdrawn. /// @return amount0 amount of token0 withdrawn. /// @return amount1 amount of token1 withdrawn. function withdraw( address receiver_, uint256 proportion_ ) external returns (uint256 amount0, uint256 amount1); /// @notice function used by metaVault or manager to get manager fees. /// @return amount0 amount of token0 sent to manager. /// @return amount1 amount of token1 sent to manager. function withdrawManagerBalance() external returns (uint256 amount0, uint256 amount1); /// @notice function used to set manager fees. /// @param newFeePIPS_ new fee that will be applied. function setManagerFeePIPS(uint256 newFeePIPS_) external; // #region view functions. /// @notice function used to get metaVault as IArrakisMetaVault. /// @return metaVault that implement IArrakisMetaVault. function metaVault() external view returns (IArrakisMetaVault); /// @notice function used to get the address that can pause the module. /// @return guardian address of the pauser. function guardian() external view returns (address); /// @notice function used to get manager token0 balance. /// @dev amount of fees in token0 that manager have not taken yet. /// @return managerBalance0 amount of token0 that manager earned. function managerBalance0() external view returns (uint256); /// @notice function used to get manager token1 balance. /// @dev amount of fees in token1 that manager have not taken yet. /// @return managerBalance1 amount of token1 that manager earned. function managerBalance1() external view returns (uint256); /// @notice function used to get manager fees. /// @return managerFeePIPS amount of token1 that manager earned. function managerFeePIPS() external view returns (uint256); /// @notice function used to get token0 as IERC20Metadata. /// @return token0 as IERC20Metadata. function token0() external view returns (IERC20Metadata); /// @notice function used to get token0 as IERC20Metadata. /// @return token1 as IERC20Metadata. function token1() external view returns (IERC20Metadata); /// @notice function used to get the initial amounts needed to open a position. /// @return init0 the amount of token0 needed to open a position. /// @return init1 the amount of token1 needed to open a position. function getInits() external view returns (uint256 init0, uint256 init1); /// @notice function used to get the amount of token0 and token1 sitting /// on the position. /// @return amount0 the amount of token0 sitting on the position. /// @return amount1 the amount of token1 sitting on the position. function totalUnderlying() external view returns (uint256 amount0, uint256 amount1); /// @notice function used to get the amounts of token0 and token1 sitting /// on the position for a specific price. /// @param priceX96_ price at which we want to simulate our tokens composition /// @return amount0 the amount of token0 sitting on the position for priceX96. /// @return amount1 the amount of token1 sitting on the position for priceX96. function totalUnderlyingAtPrice(uint160 priceX96_) external view returns (uint256 amount0, uint256 amount1); /// @notice function used to validate if module state is not manipulated /// before rebalance. /// @param oracle_ oracle that will used to check internal state. /// @param maxDeviation_ maximum deviation allowed. function validateRebalance( IOracleWrapper oracle_, uint24 maxDeviation_ ) external view; // #endregion view function. }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface 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.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.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 `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, 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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IOracleWrapper { // #region errors. error AddressZero(); error DecimalsToken0Zero(); error DecimalsToken1Zero(); // #endregion errors. /// @notice function used to get price0. /// @return price0 price of token0/token1. function getPrice0() external view returns (uint256 price0); /// @notice function used to get price1. /// @return price1 price of token1/token0. function getPrice1() external view returns (uint256 price1); }
// 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.9.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) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@solady/contracts/=lib/solady/src/", "@create3/contracts/=lib/create3/contracts/", "@v3-lib-0.8/contracts/=lib/v3-lib-0.8/contracts/", "forge-std/=lib/forge-std/src/", "@valantis-hot/contracts/=lib/valantis-hot/src/", "@valantis-core/contracts/=lib/valantis-hot/lib/valantis-core/src/", "@valantis-hot/contracts-test/=lib/valantis-hot/test/", "@ensdomains/=lib/v4-periphery/lib/v4-core/node_modules/@ensdomains/", "@uniswap/v3-core/=lib/valantis-hot/lib/v3-core/", "@uniswap/v3-periphery/=lib/valantis-hot/lib/v3-periphery/", "@uniswap/v4-core/=lib/v4-periphery/lib/v4-core/", "automate/=lib/automate/contracts/", "create3/=lib/create3/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-gas-snapshot/=lib/v4-periphery/lib/forge-gas-snapshot/src/", "hardhat/=lib/v4-periphery/lib/v4-core/node_modules/hardhat/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solady/=lib/solady/", "solmate/=lib/v4-periphery/lib/solmate/src/", "v3-core/=lib/valantis-hot/lib/v3-core/contracts/", "v3-lib-0.8/=lib/v3-lib-0.8/contracts/", "v3-periphery/=lib/valantis-hot/lib/v3-periphery/contracts/", "v4-core/=lib/v4-periphery/lib/v4-core/src/", "v4-periphery/=lib/v4-periphery/contracts/", "valantis-core/=lib/valantis-hot/lib/valantis-core/", "valantis-hot/=lib/valantis-hot/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token0_","type":"address"},{"internalType":"address","name":"token1_","type":"address"}],"name":"getMetaDatas","outputs":[{"internalType":"uint8","name":"decimals0","type":"uint8"},{"internalType":"uint8","name":"decimals1","type":"uint8"},{"internalType":"string","name":"symbol0","type":"string"},{"internalType":"string","name":"symbol1","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040518060400160405280601681526020017f417272616b69732050726976617465204c50204e46540000000000000000000081525060405180604001604052806007815260200166415252414b495360c81b8152508160009081620000799190620001c9565b506001620000888282620001c9565b5050506200009c33620000da60201b60201c565b604051620000aa9062000116565b604051809103906000f080158015620000c7573d6000803e3d6000fd5b506001600160a01b031660805262000295565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6108cf806200234e83390190565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200014f57607f821691505b6020821081036200017057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001c457600081815260208120601f850160051c810160208610156200019f5750805b601f850160051c820191505b81811015620001c057828155600101620001ab565b5050505b505050565b81516001600160401b03811115620001e557620001e562000124565b620001fd81620001f684546200013a565b8462000176565b602080601f8311600181146200023557600084156200021c5750858301515b600019600386901b1c1916600185901b178555620001c0565b600085815260208120601f198616915b82811015620002665788860151825594840194600190910190840162000245565b5085821015620002855787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b608051612096620002b86000396000818161033e0152610c9801526120966000f3fe6080604052600436106101805760003560e01c806370a08231116100d6578063b88d4fde1161007f578063f04e283e11610059578063f04e283e14610452578063f2fde38b14610465578063fee81cf41461047857600080fd5b8063b88d4fde146103c9578063c87b56dd146103e9578063e985e9c51461040957600080fd5b80638da5cb5b116100b05780638da5cb5b1461036057806395d89b4114610394578063a22cb465146103a957600080fd5b806370a08231146102f6578063715018a61461032457806388b94c951461032c57600080fd5b806323b872dd1161013857806342842e0e1161011257806342842e0e146102ae57806354d1f13d146102ce5780636352211e146102d657600080fd5b806323b872dd14610266578063256929621461028657806340c10f191461028e57600080fd5b8063074a3c3b11610169578063074a3c3b146101dc578063081812fc1461020c578063095ea7b31461024457600080fd5b806301ffc9a71461018557806306fdde03146101ba575b600080fd5b34801561019157600080fd5b506101a56101a0366004611aa5565b6104ab565b60405190151581526020015b60405180910390f35b3480156101c657600080fd5b506101cf610590565b6040516101b19190611b19565b3480156101e857600080fd5b506101fc6101f7366004611b41565b610622565b6040516101b19493929190611b7a565b34801561021857600080fd5b5061022c610227366004611bbc565b6107c9565b6040516001600160a01b0390911681526020016101b1565b34801561025057600080fd5b5061026461025f366004611bd5565b6107f0565b005b34801561027257600080fd5b50610264610281366004611c01565b610926565b6102646109ad565b34801561029a57600080fd5b506102646102a9366004611bd5565b6109fd565b3480156102ba57600080fd5b506102646102c9366004611c01565b610a13565b610264610a2e565b3480156102e257600080fd5b5061022c6102f1366004611bbc565b610a6a565b34801561030257600080fd5b50610316610311366004611c42565b610acf565b6040519081526020016101b1565b610264610b69565b34801561033857600080fd5b5061022c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561036c57600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275461022c565b3480156103a057600080fd5b506101cf610b7d565b3480156103b557600080fd5b506102646103c4366004611c5f565b610b8c565b3480156103d557600080fd5b506102646103e4366004611d1a565b610b97565b3480156103f557600080fd5b506101cf610404366004611bbc565b610c25565b34801561041557600080fd5b506101a5610424366004611b41565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b610264610460366004611c42565b61105d565b610264610473366004611c42565b61109d565b34801561048457600080fd5b50610316610493366004611c42565b63389a75e1600c908152600091909152602090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061053e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061058a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606000805461059f90611dc9565b80601f01602080910402602001604051908101604052809291908181526020018280546105cb90611dc9565b80156106185780601f106105ed57610100808354040283529160200191610618565b820191906000526020600020905b8154815290600101906020018083116105fb57829003601f168201915b5050505050905090565b600080606080856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190611e32565b9350846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ee9190611e32565b9250856001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561072e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107569190810190611e92565b9150846001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107be9190810190611e92565b905092959194509250565b60006107d4826110c4565b506000908152600460205260409020546001600160a01b031690565b60006107fb82610a6a565b9050806001600160a01b0316836001600160a01b0316036108895760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b336001600160a01b03821614806108a557506108a58133610424565b6109175760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610880565b6109218383611128565b505050565b61093033826111ae565b6109a25760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610880565b61092183838361122d565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b610a0561148c565b610a0f82826114c2565b5050565b61092183838360405180602001604052806000815250610b97565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6000818152600260205260408120546001600160a01b03168061058a5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610880565b60006001600160a01b038216610b4d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610880565b506001600160a01b031660009081526003602052604090205490565b610b7161148c565b610b7b60006114dc565b565b60606001805461059f90611dc9565b610a0f338383611535565b610ba133836111ae565b610c135760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610880565b610c1f84848484611621565b50505050565b60606000829050600080826001600160a01b031663c70920bc6040518163ffffffff1660e01b81526004016040805180830381865afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c909190611ec7565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638ada6b0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d189190611eeb565b9050306001600160a01b031663074a3c3b856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8b9190611eeb565b866001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190611eeb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381865afa925050508015610e7157506040513d6000823e601f3d908101601f19168201604052610e6e9190810190611f08565b60015b610f9d57806001600160a01b031663d372dcba6040518060e00160405280876001600160a01b03168152602001868152602001858152602001600460ff168152602001600460ff1681526020016040518060400160405280600481526020017f544b4e300000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600481526020017f544b4e31000000000000000000000000000000000000000000000000000000008152508152506040518263ffffffff1660e01b8152600401610f4e9190611f8d565b600060405180830381865afa158015610f6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f939190810190611e92565b9695505050505050565b846001600160a01b031663e61e01ac6040518060e001604052808b6001600160a01b031681526020018a81526020018981526020018760ff1681526020018660ff168152602001858152602001848152506040518263ffffffff1660e01b815260040161100a9190611f8d565b600060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261104f9190810190611e92565b9a9950505050505050505050565b61106561148c565b63389a75e1600c52806000526020600c20805442111561108d57636f5e88186000526004601cfd5b6000905561109a816114dc565b50565b6110a561148c565b8060601b6110bb57637448fbae6000526004601cfd5b61109a816114dc565b6000818152600260205260409020546001600160a01b031661109a5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610880565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155819061117582610a6a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806111ba83610a6a565b9050806001600160a01b0316846001600160a01b0316148061120157506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806112255750836001600160a01b031661121a846107c9565b6001600160a01b0316145b949350505050565b826001600160a01b031661124082610a6a565b6001600160a01b0316146112bc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610880565b6001600160a01b0382166113375760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610880565b826001600160a01b031661134a82610a6a565b6001600160a01b0316146113c65760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610880565b600081815260046020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081169091556001600160a01b038781168086526003855283862080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610b7b576382b429006000526004601cfd5b610a0f8282604051806020016040528060008152506116aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392780546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b816001600160a01b0316836001600160a01b0316036115965760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610880565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61162c84848461122d565b61163884848484611733565b610c1f5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b6116b483836118d4565b6116c16000848484611733565b6109215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b60006001600160a01b0384163b156118c9576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290611790903390899088908890600401612011565b6020604051808303816000875af19250505080156117cb575060408051601f3d908101601f191682019092526117c891810190612043565b60015b61187e573d8080156117f9576040519150601f19603f3d011682016040523d82523d6000602084013e6117fe565b606091505b5080516000036118765760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050611225565b506001949350505050565b6001600160a01b03821661192a5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610880565b6000818152600260205260409020546001600160a01b03161561198f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610880565b6000818152600260205260409020546001600160a01b0316156119f45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610880565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461109a57600080fd5b600060208284031215611ab757600080fd5b8135611ac281611a77565b9392505050565b60005b83811015611ae4578181015183820152602001611acc565b50506000910152565b60008151808452611b05816020860160208601611ac9565b601f01601f19169290920160200192915050565b602081526000611ac26020830184611aed565b6001600160a01b038116811461109a57600080fd5b60008060408385031215611b5457600080fd5b8235611b5f81611b2c565b91506020830135611b6f81611b2c565b809150509250929050565b60ff8516815260ff84166020820152608060408201526000611b9f6080830185611aed565b8281036060840152611bb18185611aed565b979650505050505050565b600060208284031215611bce57600080fd5b5035919050565b60008060408385031215611be857600080fd5b8235611bf381611b2c565b946020939093013593505050565b600080600060608486031215611c1657600080fd5b8335611c2181611b2c565b92506020840135611c3181611b2c565b929592945050506040919091013590565b600060208284031215611c5457600080fd5b8135611ac281611b2c565b60008060408385031215611c7257600080fd5b8235611c7d81611b2c565b915060208301358015158114611b6f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611cea57611cea611c92565b604052919050565b600067ffffffffffffffff821115611d0c57611d0c611c92565b50601f01601f191660200190565b60008060008060808587031215611d3057600080fd5b8435611d3b81611b2c565b93506020850135611d4b81611b2c565b925060408501359150606085013567ffffffffffffffff811115611d6e57600080fd5b8501601f81018713611d7f57600080fd5b8035611d92611d8d82611cf2565b611cc1565b818152886020838501011115611da757600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600181811c90821680611ddd57607f821691505b602082108103611e16577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b805160ff81168114611e2d57600080fd5b919050565b600060208284031215611e4457600080fd5b611ac282611e1c565b600082601f830112611e5e57600080fd5b8151611e6c611d8d82611cf2565b818152846020838601011115611e8157600080fd5b611225826020830160208701611ac9565b600060208284031215611ea457600080fd5b815167ffffffffffffffff811115611ebb57600080fd5b61122584828501611e4d565b60008060408385031215611eda57600080fd5b505080516020909101519092909150565b600060208284031215611efd57600080fd5b8151611ac281611b2c565b60008060008060808587031215611f1e57600080fd5b611f2785611e1c565b9350611f3560208601611e1c565b9250604085015167ffffffffffffffff80821115611f5257600080fd5b611f5e88838901611e4d565b93506060870151915080821115611f7457600080fd5b50611f8187828801611e4d565b91505092959194509250565b602081526001600160a01b038251166020820152602082015160408201526040820151606082015260ff606083015116608082015260ff60808301511660a0820152600060a083015160e060c0840152611feb610100840182611aed565b905060c0840151601f198483030160e08501526120088282611aed565b95945050505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152610f936080830184611aed565b60006020828403121561205557600080fd5b8151611ac281611a7756fea26469706673582212205f182facc9ea8cddd3023a39454a18f26f8ceb51b8dafeeea4f00e1af971d09d64736f6c63430008130033608060405234801561001057600080fd5b506108af806100206000396000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063f04e283e1161004e578063f04e283e146101dc578063f2fde38b146101ef578063fee81cf41461020257600080fd5b80638da5cb5b14610158578063c4d66de81461018c578063db6bfe90146101ac57600080fd5b806356d3163d116100a557806356d3163d146100d3578063715018a6146100f35780638ada6b0f146100fb57600080fd5b806325692962146100c157806354d1f13d146100cb575b600080fd5b6100c9610243565b005b6100c9610293565b3480156100df57600080fd5b506100c96100ee36600461081a565b6102cf565b6100c9610447565b34801561010757600080fd5b5060005461012e9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561016457600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275461012e565b34801561019857600080fd5b506100c96101a736600461081a565b61045b565b3480156101b857600080fd5b506101cc6101c736600461081a565b61063c565b604051901515815260200161014f565b6100c96101ea36600461081a565b6106b3565b6100c96101fd36600461081a565b6106f3565b34801561020e57600080fd5b5061023561021d36600461081a565b63389a75e1600c908152600091909152602090205490565b60405190815260200161014f565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6102d761071a565b6040517fdb6bfe9000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152600090309063db6bfe9090602401602060405180830381865afa92505050801561037e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261037b91810190610857565b60015b61038a5750600061038d565b90505b806103c4576040517f0b089cc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8516908102919091179091556040519081527f7f35accf5fc49f4045dfd53efa3f23777d4b5acf08e6ddc6ed70276550ff9132906020015b60405180910390a15050565b61044f61071a565b6104596000610750565b565b600054610100900460ff161580801561047b5750600054600160ff909116105b806104955750303b158015610495575060005460ff166001145b610525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561058357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff82166105d0576040517f9fabe1c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105d9826107b6565b801561063857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200161043b565b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166397fc015b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ad9190610857565b92915050565b6106bb61071a565b63389a75e1600c52806000526020600c2080544211156106e357636f5e88186000526004601cfd5b600090556106f081610750565b50565b6106fb61071a565b8060601b61071157637448fbae6000526004601cfd5b6106f081610750565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610459576382b429006000526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b73ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b60006020828403121561082c57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461085057600080fd5b9392505050565b60006020828403121561086957600080fd5b8151801515811461085057600080fdfea2646970667358221220179fdb3c06dbef6123453db303abcb94a8bc081bf97279f349ba7518509de57a64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106101805760003560e01c806370a08231116100d6578063b88d4fde1161007f578063f04e283e11610059578063f04e283e14610452578063f2fde38b14610465578063fee81cf41461047857600080fd5b8063b88d4fde146103c9578063c87b56dd146103e9578063e985e9c51461040957600080fd5b80638da5cb5b116100b05780638da5cb5b1461036057806395d89b4114610394578063a22cb465146103a957600080fd5b806370a08231146102f6578063715018a61461032457806388b94c951461032c57600080fd5b806323b872dd1161013857806342842e0e1161011257806342842e0e146102ae57806354d1f13d146102ce5780636352211e146102d657600080fd5b806323b872dd14610266578063256929621461028657806340c10f191461028e57600080fd5b8063074a3c3b11610169578063074a3c3b146101dc578063081812fc1461020c578063095ea7b31461024457600080fd5b806301ffc9a71461018557806306fdde03146101ba575b600080fd5b34801561019157600080fd5b506101a56101a0366004611aa5565b6104ab565b60405190151581526020015b60405180910390f35b3480156101c657600080fd5b506101cf610590565b6040516101b19190611b19565b3480156101e857600080fd5b506101fc6101f7366004611b41565b610622565b6040516101b19493929190611b7a565b34801561021857600080fd5b5061022c610227366004611bbc565b6107c9565b6040516001600160a01b0390911681526020016101b1565b34801561025057600080fd5b5061026461025f366004611bd5565b6107f0565b005b34801561027257600080fd5b50610264610281366004611c01565b610926565b6102646109ad565b34801561029a57600080fd5b506102646102a9366004611bd5565b6109fd565b3480156102ba57600080fd5b506102646102c9366004611c01565b610a13565b610264610a2e565b3480156102e257600080fd5b5061022c6102f1366004611bbc565b610a6a565b34801561030257600080fd5b50610316610311366004611c42565b610acf565b6040519081526020016101b1565b610264610b69565b34801561033857600080fd5b5061022c7f0000000000000000000000001cc0adff599f244f036a5c2425f646aef884149d81565b34801561036c57600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275461022c565b3480156103a057600080fd5b506101cf610b7d565b3480156103b557600080fd5b506102646103c4366004611c5f565b610b8c565b3480156103d557600080fd5b506102646103e4366004611d1a565b610b97565b3480156103f557600080fd5b506101cf610404366004611bbc565b610c25565b34801561041557600080fd5b506101a5610424366004611b41565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b610264610460366004611c42565b61105d565b610264610473366004611c42565b61109d565b34801561048457600080fd5b50610316610493366004611c42565b63389a75e1600c908152600091909152602090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061053e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061058a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606000805461059f90611dc9565b80601f01602080910402602001604051908101604052809291908181526020018280546105cb90611dc9565b80156106185780601f106105ed57610100808354040283529160200191610618565b820191906000526020600020905b8154815290600101906020018083116105fb57829003601f168201915b5050505050905090565b600080606080856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190611e32565b9350846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ee9190611e32565b9250856001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561072e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107569190810190611e92565b9150846001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107be9190810190611e92565b905092959194509250565b60006107d4826110c4565b506000908152600460205260409020546001600160a01b031690565b60006107fb82610a6a565b9050806001600160a01b0316836001600160a01b0316036108895760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b336001600160a01b03821614806108a557506108a58133610424565b6109175760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610880565b6109218383611128565b505050565b61093033826111ae565b6109a25760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610880565b61092183838361122d565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b610a0561148c565b610a0f82826114c2565b5050565b61092183838360405180602001604052806000815250610b97565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6000818152600260205260408120546001600160a01b03168061058a5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610880565b60006001600160a01b038216610b4d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610880565b506001600160a01b031660009081526003602052604090205490565b610b7161148c565b610b7b60006114dc565b565b60606001805461059f90611dc9565b610a0f338383611535565b610ba133836111ae565b610c135760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206f7220617070726f766564000000000000000000000000000000000000006064820152608401610880565b610c1f84848484611621565b50505050565b60606000829050600080826001600160a01b031663c70920bc6040518163ffffffff1660e01b81526004016040805180830381865afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c909190611ec7565b9150915060007f0000000000000000000000001cc0adff599f244f036a5c2425f646aef884149d6001600160a01b0316638ada6b0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d189190611eeb565b9050306001600160a01b031663074a3c3b856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8b9190611eeb565b866001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190611eeb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401600060405180830381865afa925050508015610e7157506040513d6000823e601f3d908101601f19168201604052610e6e9190810190611f08565b60015b610f9d57806001600160a01b031663d372dcba6040518060e00160405280876001600160a01b03168152602001868152602001858152602001600460ff168152602001600460ff1681526020016040518060400160405280600481526020017f544b4e300000000000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600481526020017f544b4e31000000000000000000000000000000000000000000000000000000008152508152506040518263ffffffff1660e01b8152600401610f4e9190611f8d565b600060405180830381865afa158015610f6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f939190810190611e92565b9695505050505050565b846001600160a01b031663e61e01ac6040518060e001604052808b6001600160a01b031681526020018a81526020018981526020018760ff1681526020018660ff168152602001858152602001848152506040518263ffffffff1660e01b815260040161100a9190611f8d565b600060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261104f9190810190611e92565b9a9950505050505050505050565b61106561148c565b63389a75e1600c52806000526020600c20805442111561108d57636f5e88186000526004601cfd5b6000905561109a816114dc565b50565b6110a561148c565b8060601b6110bb57637448fbae6000526004601cfd5b61109a816114dc565b6000818152600260205260409020546001600160a01b031661109a5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610880565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155819061117582610a6a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806111ba83610a6a565b9050806001600160a01b0316846001600160a01b0316148061120157506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806112255750836001600160a01b031661121a846107c9565b6001600160a01b0316145b949350505050565b826001600160a01b031661124082610a6a565b6001600160a01b0316146112bc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610880565b6001600160a01b0382166113375760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610880565b826001600160a01b031661134a82610a6a565b6001600160a01b0316146113c65760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610880565b600081815260046020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081169091556001600160a01b038781168086526003855283862080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610b7b576382b429006000526004601cfd5b610a0f8282604051806020016040528060008152506116aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392780546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b816001600160a01b0316836001600160a01b0316036115965760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610880565b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b61162c84848461122d565b61163884848484611733565b610c1f5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b6116b483836118d4565b6116c16000848484611733565b6109215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b60006001600160a01b0384163b156118c9576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290611790903390899088908890600401612011565b6020604051808303816000875af19250505080156117cb575060408051601f3d908101601f191682019092526117c891810190612043565b60015b61187e573d8080156117f9576040519150601f19603f3d011682016040523d82523d6000602084013e6117fe565b606091505b5080516000036118765760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610880565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050611225565b506001949350505050565b6001600160a01b03821661192a5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610880565b6000818152600260205260409020546001600160a01b03161561198f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610880565b6000818152600260205260409020546001600160a01b0316156119f45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610880565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461109a57600080fd5b600060208284031215611ab757600080fd5b8135611ac281611a77565b9392505050565b60005b83811015611ae4578181015183820152602001611acc565b50506000910152565b60008151808452611b05816020860160208601611ac9565b601f01601f19169290920160200192915050565b602081526000611ac26020830184611aed565b6001600160a01b038116811461109a57600080fd5b60008060408385031215611b5457600080fd5b8235611b5f81611b2c565b91506020830135611b6f81611b2c565b809150509250929050565b60ff8516815260ff84166020820152608060408201526000611b9f6080830185611aed565b8281036060840152611bb18185611aed565b979650505050505050565b600060208284031215611bce57600080fd5b5035919050565b60008060408385031215611be857600080fd5b8235611bf381611b2c565b946020939093013593505050565b600080600060608486031215611c1657600080fd5b8335611c2181611b2c565b92506020840135611c3181611b2c565b929592945050506040919091013590565b600060208284031215611c5457600080fd5b8135611ac281611b2c565b60008060408385031215611c7257600080fd5b8235611c7d81611b2c565b915060208301358015158114611b6f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611cea57611cea611c92565b604052919050565b600067ffffffffffffffff821115611d0c57611d0c611c92565b50601f01601f191660200190565b60008060008060808587031215611d3057600080fd5b8435611d3b81611b2c565b93506020850135611d4b81611b2c565b925060408501359150606085013567ffffffffffffffff811115611d6e57600080fd5b8501601f81018713611d7f57600080fd5b8035611d92611d8d82611cf2565b611cc1565b818152886020838501011115611da757600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600181811c90821680611ddd57607f821691505b602082108103611e16577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b805160ff81168114611e2d57600080fd5b919050565b600060208284031215611e4457600080fd5b611ac282611e1c565b600082601f830112611e5e57600080fd5b8151611e6c611d8d82611cf2565b818152846020838601011115611e8157600080fd5b611225826020830160208701611ac9565b600060208284031215611ea457600080fd5b815167ffffffffffffffff811115611ebb57600080fd5b61122584828501611e4d565b60008060408385031215611eda57600080fd5b505080516020909101519092909150565b600060208284031215611efd57600080fd5b8151611ac281611b2c565b60008060008060808587031215611f1e57600080fd5b611f2785611e1c565b9350611f3560208601611e1c565b9250604085015167ffffffffffffffff80821115611f5257600080fd5b611f5e88838901611e4d565b93506060870151915080821115611f7457600080fd5b50611f8187828801611e4d565b91505092959194509250565b602081526001600160a01b038251166020820152602082015160408201526040820151606082015260ff606083015116608082015260ff60808301511660a0820152600060a083015160e060c0840152611feb610100840182611aed565b905060c0840151601f198483030160e08501526120088282611aed565b95945050505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152610f936080830184611aed565b60006020828403121561205557600080fd5b8151611ac281611a7756fea26469706673582212205f182facc9ea8cddd3023a39454a18f26f8ceb51b8dafeeea4f00e1af971d09d64736f6c63430008130033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.