├── src ├── hooks │ ├── index.ts │ └── useContracts │ │ └── index.ts ├── contexts │ ├── index.ts │ └── ContractsContext │ │ └── index.tsx ├── react-app-env.d.ts ├── assets │ ├── edit.png │ ├── ethlogo.png │ ├── question.png │ └── polygonlogo.png ├── artifacts │ └── contracts │ │ └── Domains.sol │ │ ├── Domains.dbg.json │ │ └── Domains.json ├── components │ ├── index.ts │ ├── Spinner │ │ ├── index.tsx │ │ └── styles.ts │ ├── Modal │ │ ├── index.tsx │ │ └── styles.ts │ ├── Header │ │ ├── index.tsx │ │ └── styles.ts │ ├── Button │ │ └── index.ts │ └── Form │ │ ├── styles.ts │ │ └── index.tsx ├── setupTests.ts ├── App.tsx ├── styles.ts ├── constants │ └── index.ts ├── index.css ├── reportWebVitals.ts ├── index.tsx ├── utils │ └── networks.ts └── types │ └── index.ts ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── docs ├── main.js.LICENSE.txt └── index.html ├── .gitignore ├── README.md ├── tsconfig.json ├── scripts ├── run.js └── deploy.js ├── hardhat.config.js ├── contracts ├── libraries │ ├── StringUtils.sol │ └── Base64.sol └── Domains.sol └── package.json /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./useContracts"; 2 | -------------------------------------------------------------------------------- /src/contexts/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ContractsContext"; 2 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/src/assets/edit.png -------------------------------------------------------------------------------- /src/assets/ethlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/src/assets/ethlogo.png -------------------------------------------------------------------------------- /src/assets/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/src/assets/question.png -------------------------------------------------------------------------------- /src/assets/polygonlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablopoggiog/polygon-name-service/HEAD/src/assets/polygonlogo.png -------------------------------------------------------------------------------- /docs/main.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.14 3 | * (c) 2014-2021 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | .env.local 4 | coverage 5 | coverage.json 6 | typechain 7 | 8 | #Hardhat files 9 | cache 10 | -------------------------------------------------------------------------------- /src/artifacts/contracts/Domains.sol/Domains.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../build-info/9a36ac6a828954ecb5bf73c69627ec38.json" 4 | } 5 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Form"; 2 | export * from "./Header"; 3 | export * from "./Button"; 4 | export * from "./Spinner"; 5 | export * from "./Modal"; 6 | -------------------------------------------------------------------------------- /src/hooks/useContracts/index.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { ContractsContext } from "src/contexts"; 3 | 4 | export const useContracts = () => useContext(ContractsContext); 5 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | Hardhat Docgen
-------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Form, Header } from "src/components"; 2 | import { Container } from "./styles"; 3 | 4 | const App = () => { 5 | return ( 6 | 7 |
8 |
9 | 10 | ); 11 | }; 12 | 13 | export default App; 14 | -------------------------------------------------------------------------------- /src/components/Spinner/index.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from "react"; 2 | import { Loader } from "./styles"; 3 | 4 | export const Spinner: FunctionComponent = () => ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | width: 100%; 7 | min-height: 100vh; 8 | background-color: #081018; 9 | color: white; 10 | align-items: center; 11 | `; 12 | -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | // using String here not to enforce the type, but to avoid using "!" (the env vars could not exist, and the type of the contants would be string | undefined) 2 | export const CONTRACT_ADDRESS = String(process.env.REACT_APP_CONTRACT_ADDRESS); 3 | 4 | export const TLD = "zed"; 5 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/components/Modal/index.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from "react"; 2 | import { Background, Container, Content } from "./styles"; 3 | 4 | interface ModalProps { 5 | content: string | JSX.Element; 6 | isOpen: boolean; 7 | } 8 | 9 | export const Modal: FunctionComponent = ({ content, isOpen }) => { 10 | return ( 11 | 12 | 13 | {content} 14 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat accounts 9 | npx hardhat compile 10 | npx hardhat clean 11 | npx hardhat test 12 | npx hardhat node 13 | node scripts/sample-script.js 14 | npx hardhat help 15 | ``` 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx", 22 | "baseUrl": ".", 23 | }, 24 | "include": [ 25 | "src" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { ContractsProvider } from "src/contexts"; 4 | import "./index.css"; 5 | import App from "./App"; 6 | import reportWebVitals from "./reportWebVitals"; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById("root") 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | -------------------------------------------------------------------------------- /src/utils/networks.ts: -------------------------------------------------------------------------------- 1 | const networks = { 2 | "0x1": "Mainnet", 3 | "0x3": "Ropsten", 4 | "0x2a": "Kovan", 5 | "0x4": "Rinkeby", 6 | "0x5": "Goerli", 7 | "0x61": "BSC Testnet", 8 | "0x38": "BSC Mainnet", 9 | "0x89": "Polygon Mainnet", 10 | "0x13881": "Polygon Mumbai Testnet", 11 | "0xa86a": "AVAX Mainnet", 12 | }; 13 | 14 | export const mumbaiNetwork = { 15 | chainId: "0x13881", 16 | chainName: "Polygon Mumbai Testnet", 17 | rpcUrls: ["https://rpc-mumbai.maticvigil.com/"], 18 | nativeCurrency: { 19 | name: "Mumbai Matic", 20 | symbol: "MATIC", 21 | decimals: 18, 22 | }, 23 | blockExplorerUrls: ["https://mumbai.polygonscan.com/"], 24 | }; 25 | 26 | export { networks }; 27 | -------------------------------------------------------------------------------- /src/components/Modal/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | interface BackgroundProps { 4 | isOpen: boolean; 5 | } 6 | 7 | export const Background = styled.div` 8 | background: rgba(0, 0, 0, 0.7); 9 | position: fixed; 10 | bottom: 0; 11 | top: 0; 12 | right: 0; 13 | left: 0; 14 | width: 100vw; 15 | height: 100vh; 16 | z-index: 90; 17 | display: ${({ isOpen }) => (isOpen ? "flex" : "none")}; 18 | align-items: center; 19 | justify-content: center; 20 | `; 21 | 22 | export const Container = styled.div` 23 | display: flex; 24 | flex-direction: column; 25 | color: white; 26 | border-radius: 5px; 27 | width: 80%; 28 | max-width: 500px; 29 | padding: 1em 1.4em; 30 | word-break: break-word; 31 | `; 32 | 33 | export const Content = styled.div` 34 | padding: 1em; 35 | `; 36 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | import { networks } from "src/utils/networks"; 2 | 3 | declare global { 4 | interface Window { 5 | ethereum?: any; 6 | } 7 | } 8 | 9 | export interface IContractsContext { 10 | currentAccount: string; 11 | connectWallet: () => void; 12 | mintDomain: MintOrUpdateDomain; 13 | network: string; 14 | switchNetwork: () => void; 15 | updateDomain: MintOrUpdateDomain; 16 | mints: IRecord[]; 17 | isLoadingDomains: boolean; 18 | } 19 | 20 | export type MintOrUpdateDomain = (params: { 21 | domain: string; 22 | record: string; 23 | setRecord: (record: string) => void; 24 | setDomain: (domain: string) => void; 25 | setIsLoading: (isLoading: boolean) => void; 26 | }) => void; 27 | 28 | export type Network = keyof typeof networks; 29 | 30 | export interface IRecord { 31 | id: number; 32 | name: string; 33 | record: any; 34 | owner: any; 35 | } 36 | -------------------------------------------------------------------------------- /scripts/run.js: -------------------------------------------------------------------------------- 1 | const main = async () => { 2 | const domainContractFactory = await hre.ethers.getContractFactory("Domains"); 3 | const TLD = "zed"; 4 | const domainContract = await domainContractFactory.deploy(TLD); 5 | await domainContract.deployed(); 6 | 7 | console.log("Contract deployed to:", domainContract.address); 8 | 9 | let txn = await domainContract.register("lord", { 10 | value: hre.ethers.utils.parseEther("0.3"), 11 | }); 12 | await txn.wait(); 13 | 14 | const address = await domainContract.getAddress("lord"); 15 | console.log(`Owner of domain lord.${TLD}:`, address); 16 | 17 | const balance = await hre.ethers.provider.getBalance(domainContract.address); 18 | console.log("Contract balance:", hre.ethers.utils.formatEther(balance)); 19 | }; 20 | 21 | const runMain = async () => { 22 | try { 23 | await main(); 24 | process.exit(0); 25 | } catch (error) { 26 | console.log(error); 27 | process.exit(1); 28 | } 29 | }; 30 | 31 | runMain(); 32 | -------------------------------------------------------------------------------- /src/components/Spinner/styles.ts: -------------------------------------------------------------------------------- 1 | import styled, { keyframes } from "styled-components"; 2 | 3 | const spin = keyframes` 4 | 0% { 5 | transform: rotate(0deg); 6 | } 7 | 8 | 50% { 9 | transform: rotate(180deg); 10 | opacity: 0.6; 11 | } 12 | 13 | 100% { 14 | transform: rotate(360deg); 15 | opacity: 1; 16 | } 17 | `; 18 | 19 | interface LoaderProps { 20 | inner?: boolean; 21 | innest?: boolean; 22 | } 23 | 24 | export const Loader = styled.div` 25 | border: 16px solid lightBlue; 26 | border-top: 16px solid rgba(255, 219, 220); 27 | border-radius: 50%; 28 | animation: ${spin} 2s linear infinite; 29 | margin: 0 auto; 30 | display: flex; 31 | align-items: center; 32 | justify-content: center; 33 | width: ${({ inner, innest }) => (inner ? "67px" : innest ? "15px" : "120px")}; 34 | height: ${({ inner, innest }) => 35 | inner ? "67px" : innest ? "15px" : "120px"}; 36 | `; 37 | -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | require("hardhat-docgen"); 3 | require("dotenv").config(); 4 | 5 | // This is a sample Hardhat task. To learn how to create your own go to 6 | // https://hardhat.org/guides/create-task.html 7 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 8 | const accounts = await hre.ethers.getSigners(); 9 | 10 | for (const account of accounts) { 11 | console.log(account.address); 12 | } 13 | }); 14 | 15 | // You need to export an object to set up your config 16 | // Go to https://hardhat.org/config/ to learn more 17 | 18 | /** 19 | * @type import('hardhat/config').HardhatUserConfig 20 | */ 21 | module.exports = { 22 | solidity: "0.8.10", 23 | docgen: { 24 | path: "./docs", 25 | clear: true, 26 | runOnCompile: false, 27 | }, 28 | paths: { 29 | artifacts: "./src/artifacts", 30 | }, 31 | networks: { 32 | mumbai: { 33 | url: process.env.ALCHEMY_KEY, 34 | accounts: [process.env.PRIVATE_KEY], 35 | }, 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /contracts/libraries/StringUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Source: 3 | // https://github.com/ensdomains/ens-contracts/blob/master/contracts/ethregistrar/StringUtils.sol 4 | pragma solidity >=0.8.4; 5 | 6 | library StringUtils { 7 | /** 8 | * @dev Returns the length of a given string 9 | * 10 | * @param s The string to measure the length of 11 | * @return The length of the input string 12 | */ 13 | function strlen(string memory s) internal pure returns (uint256) { 14 | uint256 len; 15 | uint256 i = 0; 16 | uint256 bytelength = bytes(s).length; 17 | for (len = 0; i < bytelength; len++) { 18 | bytes1 b = bytes(s)[i]; 19 | if (b < 0x80) { 20 | i += 1; 21 | } else if (b < 0xE0) { 22 | i += 2; 23 | } else if (b < 0xF0) { 24 | i += 3; 25 | } else if (b < 0xF8) { 26 | i += 4; 27 | } else if (b < 0xFC) { 28 | i += 5; 29 | } else { 30 | i += 6; 31 | } 32 | } 33 | return len; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from "react"; 2 | import { useContracts } from "src/hooks"; 3 | import polygonLogo from "src/assets/polygonlogo.png"; 4 | import ethLogo from "src/assets/ethlogo.png"; 5 | import question from "src/assets/question.png"; 6 | import { Container, Title, Image, WalletStatus } from "./styles"; 7 | 8 | export const Header: FunctionComponent = () => { 9 | const { currentAccount, network } = useContracts(); 10 | 11 | return ( 12 | 13 | 🏇 Zed Name Service 🏇 14 | 15 | Network logo 25 | {currentAccount ? ( 26 |

27 | {" "} 28 | Wallet: {currentAccount.slice(0, 6)}... 29 | {currentAccount.slice(-4)}{" "} 30 |

31 | ) : ( 32 |

Not connected

33 | )} 34 |
35 |
36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /src/components/Button/index.ts: -------------------------------------------------------------------------------- 1 | import styled, { keyframes } from "styled-components"; 2 | 3 | const gradientAnimation = keyframes` 4 | 0% { 5 | background-position: 0% 50%; 6 | } 7 | 50% { 8 | background-position: 100% 50%; 9 | } 10 | 100% { 11 | background-position: 0% 50%; 12 | } 13 | } 14 | `; 15 | 16 | interface ButtonProps { 17 | disabled?: boolean; 18 | } 19 | 20 | export const Button = styled.button` 21 | border-radius: 1em; 22 | padding: 14px; 23 | cursor: ${({ disabled }) => !disabled && "pointer"}; 24 | will-change: transform; 25 | background: ${({ disabled }) => 26 | disabled 27 | ? "-webkit-linear-gradient(left, rgba(105, 105, 105), rgba(105, 105, 105, 0.1))" 28 | : "-webkit-linear-gradient(left, #a200d6, rgba(130, 71, 229, 0.6))"}; 29 | background-size: 200% 200%; 30 | width: 100%; 31 | border: none; 32 | color: linear-gradient(left, #a200d6, rgba(130, 71, 229, 0.7)); 33 | color: white; 34 | font-size: 1em; 35 | animation: ${gradientAnimation} 4s ease infinite; 36 | transition: 0.5s; 37 | 38 | &:hover { 39 | transform: ${({ disabled }) => !disabled && "scale(1.02)"}; 40 | } 41 | `; 42 | -------------------------------------------------------------------------------- /scripts/deploy.js: -------------------------------------------------------------------------------- 1 | const main = async () => { 2 | const domainContractFactory = await hre.ethers.getContractFactory("Domains"); 3 | const TLD = "zed"; 4 | const domainContract = await domainContractFactory.deploy(TLD); 5 | await domainContract.deployed(); 6 | 7 | console.log("Contract deployed to:", domainContract.address); 8 | 9 | let txn = await domainContract.register("jors", { 10 | value: hre.ethers.utils.parseEther("0.3"), 11 | }); 12 | await txn.wait(); 13 | console.log(`Minted domain jors.${TLD}`); 14 | 15 | txn = await domainContract.setRecord("jors", `Am I a jors or a ${TLD}??`); 16 | await txn.wait(); 17 | console.log(`Set record for jors.${TLD}`); 18 | 19 | const address = await domainContract.getAddress("jors"); 20 | console.log("Owner of domain jors:", address); 21 | 22 | const balance = await hre.ethers.provider.getBalance(domainContract.address); 23 | console.log("Contract balance:", hre.ethers.utils.formatEther(balance)); 24 | }; 25 | 26 | const runMain = async () => { 27 | try { 28 | await main(); 29 | process.exit(0); 30 | } catch (error) { 31 | console.log(error); 32 | process.exit(1); 33 | } 34 | }; 35 | 36 | runMain(); 37 | -------------------------------------------------------------------------------- /src/components/Header/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Container = styled.header` 4 | display: flex; 5 | width: 100%; 6 | background-color: #081018; 7 | color: white; 8 | align-items: center; 9 | justify-content: space-around; 10 | 11 | @media (max-width: 768px) { 12 | flex-direction: column; 13 | font-size: 0.7em; 14 | } 15 | 16 | @media (max-width: 500px) { 17 | font-size: 0.6em; 18 | } 19 | `; 20 | 21 | export const Title = styled.h1` 22 | font-size: 2em; 23 | font-weight: 600; 24 | display: flex; 25 | background: black; 26 | border-radius: 16px; 27 | padding: 12px 20px; 28 | margin-right: 10%; 29 | text-align: center; 30 | 31 | @media (max-width: 768px) { 32 | padding: 2rem; 33 | margin: 1rem; 34 | } 35 | `; 36 | 37 | export const WalletStatus = styled.div` 38 | display: flex; 39 | align-items: center; 40 | justify-content: space-around; 41 | text-align: left; 42 | margin-left: 10%; 43 | 44 | @media (max-width: 768px) { 45 | padding: 2rem; 46 | margin: 1rem; 47 | } 48 | `; 49 | 50 | export const Image = styled.img` 51 | width: 20px; 52 | height: 20px; 53 | margin-right: 10px; 54 | `; 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polygon-name-service", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "react-scripts start", 8 | "build": "react-scripts build", 9 | "test": "react-scripts test", 10 | "eject": "react-scripts eject" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "@nomiclabs/hardhat-ethers": "^2.0.5", 17 | "@nomiclabs/hardhat-waffle": "^2.0.2", 18 | "@types/styled-components": "^5.1.23", 19 | "chai": "^4.3.6", 20 | "ethereum-waffle": "^3.4.0", 21 | "ethers": "^5.5.4", 22 | "hardhat": "^2.8.4", 23 | "hardhat-docgen": "^1.3.0" 24 | }, 25 | "dependencies": { 26 | "@openzeppelin/contracts": "^4.5.0", 27 | "@testing-library/jest-dom": "^5.16.2", 28 | "@testing-library/react": "^12.1.3", 29 | "@testing-library/user-event": "^13.5.0", 30 | "@types/jest": "^27.4.0", 31 | "@types/node": "^16.11.25", 32 | "@types/react": "^17.0.39", 33 | "@types/react-dom": "^17.0.11", 34 | "react": "^17.0.2", 35 | "react-dom": "^17.0.2", 36 | "react-scripts": "5.0.0", 37 | "styled-components": "^5.3.3", 38 | "typescript": "^4.5.5", 39 | "web-vitals": "^2.1.4" 40 | }, 41 | "eslintConfig": { 42 | "extends": [ 43 | "react-app", 44 | "react-app/jest" 45 | ] 46 | }, 47 | "browserslist": { 48 | "production": [ 49 | ">0.2%", 50 | "not dead", 51 | "not op_mini all" 52 | ], 53 | "development": [ 54 | "last 1 chrome version", 55 | "last 1 firefox version", 56 | "last 1 safari version" 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Zed Name Service 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /contracts/libraries/Base64.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2021-09-05 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.8.0; 8 | 9 | /// [MIT License] 10 | /// @title Base64 11 | /// @notice Provides a function for encoding some bytes in base64 12 | /// @author Brecht Devos 13 | library Base64 { 14 | bytes internal constant TABLE = 15 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 16 | 17 | /// @notice Encodes some bytes to the base64 representation 18 | function encode(bytes memory data) internal pure returns (string memory) { 19 | uint256 len = data.length; 20 | if (len == 0) return ""; 21 | 22 | // multiply by 4/3 rounded up 23 | uint256 encodedLen = 4 * ((len + 2) / 3); 24 | 25 | // Add some extra buffer at the end 26 | bytes memory result = new bytes(encodedLen + 32); 27 | 28 | bytes memory table = TABLE; 29 | 30 | assembly { 31 | let tablePtr := add(table, 1) 32 | let resultPtr := add(result, 32) 33 | 34 | for { 35 | let i := 0 36 | } lt(i, len) { 37 | 38 | } { 39 | i := add(i, 3) 40 | let input := and(mload(add(data, i)), 0xffffff) 41 | 42 | let out := mload(add(tablePtr, and(shr(18, input), 0x3F))) 43 | out := shl(8, out) 44 | out := add( 45 | out, 46 | and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF) 47 | ) 48 | out := shl(8, out) 49 | out := add( 50 | out, 51 | and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF) 52 | ) 53 | out := shl(8, out) 54 | out := add( 55 | out, 56 | and(mload(add(tablePtr, and(input, 0x3F))), 0xFF) 57 | ) 58 | out := shl(224, out) 59 | 60 | mstore(resultPtr, out) 61 | 62 | resultPtr := add(resultPtr, 4) 63 | } 64 | 65 | switch mod(len, 3) 66 | case 1 { 67 | mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) 68 | } 69 | case 2 { 70 | mstore(sub(resultPtr, 1), shl(248, 0x3d)) 71 | } 72 | 73 | mstore(result, encodedLen) 74 | } 75 | 76 | return string(result); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/components/Form/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-around; 8 | gap: 3em; 9 | height: 100%; 10 | padding: 2rem; 11 | width: 100%; 12 | box-sizing: border-box; 13 | `; 14 | 15 | export const FormBody = styled.div` 16 | display: flex; 17 | flex-direction: column; 18 | align-items: center; 19 | justify-content: center; 20 | gap: 3em; 21 | padding: 2rem; 22 | max-width: 310px; 23 | box-sizing: border-box; 24 | `; 25 | 26 | export const ButtonsContainer = styled.div` 27 | display: flex; 28 | align-items: center; 29 | justify-content: center; 30 | gap: 1em; 31 | width: 100%; 32 | `; 33 | 34 | export const InputContainer = styled.div` 35 | display: flex; 36 | align-items: center; 37 | justify-content: center; 38 | gap: 1em; 39 | background: black; 40 | border-radius: 8px; 41 | width: 100%; 42 | 43 | & > * { 44 | padding: 14px; 45 | font-size: 1em; 46 | color: white; 47 | background: black; 48 | border: none; 49 | border-radius: 8px; 50 | } 51 | `; 52 | 53 | export const Input = styled.input` 54 | width: 100%; 55 | `; 56 | 57 | export const SwitchNetwork = styled.div` 58 | display: flex; 59 | flex-direction: column; 60 | gap: 2rem; 61 | 62 | p { 63 | text-align: center; 64 | } 65 | `; 66 | 67 | // Domains 68 | 69 | export const DomainsContainer = styled.div` 70 | display: flex; 71 | flex-direction: column; 72 | justify-content: center; 73 | width: 100%; 74 | `; 75 | 76 | export const Subtitle = styled.p` 77 | text-align: center; 78 | `; 79 | 80 | export const DomainsList = styled.div` 81 | display: flex; 82 | justify-content: center; 83 | align-items: center; 84 | gap: 2em; 85 | flex-wrap: wrap; 86 | padding: 2em 0; 87 | `; 88 | 89 | export const Domain = styled.div` 90 | min-width: 115px; 91 | display: flex; 92 | flex-direction: column; 93 | justify-content: center; 94 | align-items: center; 95 | background: rgba(130, 71, 229, 0.4); 96 | border-radius: 7px; 97 | padding: 0.8em; 98 | `; 99 | 100 | export const Row = styled.div` 101 | display: flex; 102 | justify-content: center; 103 | align-items: center; 104 | gap: 1em; 105 | width: 100%; 106 | `; 107 | 108 | export const Link = styled.a` 109 | color: white !important; 110 | `; 111 | 112 | export const Name = styled.p``; 113 | 114 | export const Image = styled.img``; 115 | 116 | export const EditButton = styled.button` 117 | height: 30px; 118 | width: 30px; 119 | border-radius: 7px; 120 | background: transparent; 121 | border: none; 122 | cursor: pointer; 123 | transition: 0.5s; 124 | 125 | &:hover { 126 | transform: scale(1.02); 127 | } 128 | `; 129 | -------------------------------------------------------------------------------- /src/components/Form/index.tsx: -------------------------------------------------------------------------------- 1 | import { FunctionComponent, useState } from "react"; 2 | import { useContracts } from "src/hooks"; 3 | import { Button, Spinner, Modal } from "src/components"; 4 | import { CONTRACT_ADDRESS, TLD } from "src/constants"; 5 | import editIcon from "src/assets/edit.png"; 6 | import { 7 | Container, 8 | FormBody, 9 | ButtonsContainer, 10 | InputContainer, 11 | Input, 12 | SwitchNetwork, 13 | DomainsContainer, 14 | Subtitle, 15 | DomainsList, 16 | Domain, 17 | Link, 18 | Name, 19 | Image, 20 | Row, 21 | EditButton, 22 | } from "./styles"; 23 | 24 | export const Form: FunctionComponent = () => { 25 | const [domain, setDomain] = useState(""); 26 | const [record, setRecord] = useState(""); 27 | const [isLoading, setIsLoading] = useState(false); 28 | const [isEditing, setIsEditing] = useState(false); 29 | 30 | const { 31 | mintDomain, 32 | network, 33 | switchNetwork, 34 | currentAccount, 35 | connectWallet, 36 | updateDomain, 37 | mints, 38 | isLoadingDomains, 39 | } = useContracts(); 40 | 41 | const handleMint = () => 42 | mintDomain({ 43 | domain, 44 | record, 45 | setRecord, 46 | setDomain, 47 | setIsLoading, 48 | }); 49 | 50 | const handleUpdateDomain = () => 51 | updateDomain({ 52 | domain, 53 | record, 54 | setRecord, 55 | setDomain, 56 | setIsLoading, 57 | }); 58 | 59 | const editRecord = (name: string) => { 60 | console.log("Editing record for", name); 61 | setIsEditing(true); 62 | setDomain(name); 63 | }; 64 | 65 | return ( 66 | 67 | 68 | {currentAccount ? ( 69 | network !== "Polygon Mumbai Testnet" ? ( 70 | 71 |

Please connect to the Polygon Mumbai Testnet

72 | 73 |
74 | ) : ( 75 | <> 76 | 77 | setDomain(e.target.value)} 83 | /> 84 | .{TLD} 85 | 86 | 87 | 88 | setRecord(e.target.value)} 94 | /> 95 | 96 | 97 | 98 | {isEditing ? ( 99 | <> 100 | 103 | 104 | 105 | ) : ( 106 | 109 | )} 110 | 111 | 112 | ) 113 | ) : ( 114 | 115 | )} 116 |
117 | 118 | {isLoadingDomains && } 119 | 120 | {currentAccount && mints.length > 0 && ( 121 | 122 | Recently minted domains! 123 | 124 | {mints.map(({ id, name, owner, record }) => ( 125 | 126 | 127 | 132 | 133 | {name}.{TLD} 134 | 135 | 136 | {/* Only editable being the owner */} 137 | {owner.toLowerCase() === currentAccount.toLowerCase() && ( 138 | editRecord(name)}> 139 | Edit button 140 | 141 | )} 142 | 143 |

{record}

144 |
145 | ))} 146 |
147 |
148 | )} 149 | 150 | } /> 151 |
152 | ); 153 | }; 154 | -------------------------------------------------------------------------------- /src/contexts/ContractsContext/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FunctionComponent, 3 | createContext, 4 | useState, 5 | useEffect, 6 | useCallback, 7 | } from "react"; 8 | import { ethers } from "ethers"; 9 | import { 10 | IContractsContext, 11 | MintOrUpdateDomain, 12 | Network, 13 | IRecord, 14 | } from "src/types"; 15 | import { CONTRACT_ADDRESS } from "src/constants"; 16 | import DOMAINS from "src/artifacts/contracts/Domains.sol/Domains.json"; 17 | import { networks, mumbaiNetwork } from "src/utils/networks"; 18 | 19 | const { ethereum } = window; 20 | 21 | export const ContractsContext = createContext({ 22 | currentAccount: "", 23 | connectWallet: () => { 24 | return; 25 | }, 26 | mintDomain: () => { 27 | return; 28 | }, 29 | network: "0x89", 30 | switchNetwork: () => { 31 | return; 32 | }, 33 | updateDomain: () => { 34 | return; 35 | }, 36 | mints: [], 37 | isLoadingDomains: false, 38 | }); 39 | 40 | export const ContractsProvider: FunctionComponent = ({ children }) => { 41 | const [currentAccount, setCurrentAccount] = useState(""); 42 | const [network, setNetwork] = useState(""); 43 | const [mints, setMints] = useState([]); 44 | const [isLoadingDomains, setIsLoadingDomains] = useState(false); 45 | 46 | const checkIfWalletIsConnected = useCallback(async () => { 47 | const accounts = await ethereum.request({ 48 | method: "eth_accounts", 49 | }); 50 | 51 | if (accounts.length !== 0) { 52 | const account = accounts[0]; 53 | console.log("Found an authorized account:", account); 54 | setCurrentAccount(account); 55 | } else { 56 | console.log("No authorized account found"); 57 | } 58 | 59 | const chainId: Network = await ethereum.request({ 60 | method: "eth_chainId", 61 | }); 62 | setNetwork(networks[chainId] || ""); 63 | 64 | ethereum.on("chainChanged", handleChainChanged); 65 | 66 | function handleChainChanged(_chainId: Network | string) { 67 | window.location.reload(); 68 | } 69 | 70 | fetchMints(); 71 | }, []); 72 | 73 | const connectWallet = async () => { 74 | try { 75 | if (!ethereum) { 76 | alert("Get MetaMask -> https://metamask.io/"); 77 | return; 78 | } 79 | 80 | // Fancy method to request access to account. 81 | const accounts = await ethereum.request({ 82 | method: "eth_requestAccounts", 83 | }); 84 | 85 | // Boom! This should print out public address once we authorize Metamask. 86 | console.log("Connected", accounts[0]); 87 | setCurrentAccount(accounts[0]); 88 | 89 | fetchMints(); 90 | } catch (error) { 91 | console.log(error); 92 | } 93 | }; 94 | 95 | const mintDomain: MintOrUpdateDomain = async ({ 96 | domain, 97 | record, 98 | setRecord, 99 | setDomain, 100 | setIsLoading, 101 | }) => { 102 | if (!domain || !record) { 103 | return; 104 | } 105 | 106 | if (domain.length < 3) { 107 | alert("Domain must be at least 3 characters long"); 108 | return; 109 | } 110 | 111 | setIsLoading(true); 112 | 113 | const price = 114 | domain.length === 3 ? "0.5" : domain.length === 4 ? "0.3" : "0.1"; 115 | console.log("Minting domain", domain, "with price", price); 116 | 117 | try { 118 | if (ethereum) { 119 | const provider = new ethers.providers.Web3Provider(ethereum); 120 | const signer = provider.getSigner(); 121 | const contract = new ethers.Contract( 122 | CONTRACT_ADDRESS, 123 | DOMAINS.abi, 124 | signer 125 | ); 126 | 127 | console.log("Going to pop wallet now to pay gas..."); 128 | 129 | let tx = await contract.register(domain, { 130 | value: ethers.utils.parseEther(price), 131 | }); 132 | 133 | const receipt = await tx.wait(); 134 | 135 | // Checks if the transaction was successfully completed 136 | if (receipt.status === 1) { 137 | console.log( 138 | "Domain minted! https://mumbai.polygonscan.com/tx/" + tx.hash 139 | ); 140 | 141 | tx = await contract.setRecord(domain, record); 142 | await tx.wait(); 143 | 144 | console.log( 145 | "Record set! https://mumbai.polygonscan.com/tx/" + tx.hash 146 | ); 147 | 148 | fetchMints(); 149 | 150 | setRecord(""); 151 | setDomain(""); 152 | } else { 153 | alert("Transaction failed! Please try again"); 154 | } 155 | } 156 | } catch (error) { 157 | console.log(error); 158 | } 159 | 160 | setIsLoading(false); 161 | }; 162 | 163 | const switchNetwork = async () => { 164 | if (ethereum) { 165 | try { 166 | // Switch to the Mumbai testnet 167 | await ethereum.request({ 168 | method: "wallet_switchEthereumChain", 169 | params: [{ chainId: mumbaiNetwork.chainId }], 170 | }); 171 | } catch (error: any) { 172 | // This error code means that the chain we want has not been added to MetaMask 173 | // In this case we ask the user to add it to their MetaMask 174 | if (error.code === 4902) { 175 | try { 176 | await ethereum.request({ 177 | method: "wallet_addEthereumChain", 178 | params: [mumbaiNetwork], 179 | }); 180 | } catch (error) { 181 | console.log(error); 182 | } 183 | } 184 | console.log(error); 185 | } 186 | } else { 187 | // If window.ethereum is not found then MetaMask is not installed 188 | alert( 189 | "MetaMask is not installed. Please install it to use this app: https://metamask.io/download.html" 190 | ); 191 | } 192 | }; 193 | 194 | const fetchMints = async () => { 195 | setIsLoadingDomains(true); 196 | 197 | try { 198 | if (ethereum) { 199 | const provider = new ethers.providers.Web3Provider(ethereum); 200 | const signer = provider.getSigner(); 201 | const contract = new ethers.Contract( 202 | CONTRACT_ADDRESS, 203 | DOMAINS.abi, 204 | signer 205 | ); 206 | 207 | const names: string[] = await contract.getAllNames(); 208 | 209 | // For each name, gets the record and the address 210 | const mintRecords: IRecord[] = await Promise.all( 211 | names.map(async (name) => { 212 | const mintRecord = await contract.records(name); 213 | const owner = await contract.domains(name); 214 | return { 215 | id: names.indexOf(name), 216 | name: name, 217 | record: mintRecord, 218 | owner: owner, 219 | }; 220 | }) 221 | ); 222 | 223 | console.log("MINTS FETCHED ", mintRecords); 224 | setMints(mintRecords); 225 | } 226 | } catch (error) { 227 | console.log(error); 228 | } 229 | 230 | setIsLoadingDomains(false); 231 | }; 232 | 233 | const updateDomain: MintOrUpdateDomain = async ({ 234 | record, 235 | domain, 236 | setIsLoading, 237 | setRecord, 238 | setDomain, 239 | }) => { 240 | if (!record || !domain) return; 241 | 242 | setIsLoading(true); 243 | console.log("Updating domain", domain, "with record", record); 244 | 245 | try { 246 | if (ethereum) { 247 | const provider = new ethers.providers.Web3Provider(ethereum); 248 | const signer = provider.getSigner(); 249 | const contract = new ethers.Contract( 250 | CONTRACT_ADDRESS, 251 | DOMAINS.abi, 252 | signer 253 | ); 254 | 255 | const tx = await contract.setRecord(domain, record); 256 | await tx.wait(); 257 | console.log("Record set https://mumbai.polygonscan.com/tx/" + tx.hash); 258 | 259 | fetchMints(); 260 | setRecord(""); 261 | setDomain(""); 262 | } 263 | } catch (error) { 264 | console.log(error); 265 | } 266 | setIsLoading(false); 267 | }; 268 | 269 | useEffect(() => { 270 | checkIfWalletIsConnected(); 271 | }, [checkIfWalletIsConnected]); 272 | 273 | return ( 274 | 286 | {children} 287 | 288 | ); 289 | }; 290 | -------------------------------------------------------------------------------- /contracts/Domains.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | 3 | pragma solidity ^0.8.10; 4 | 5 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; 6 | import "@openzeppelin/contracts/utils/Counters.sol"; 7 | import "hardhat/console.sol"; 8 | 9 | import {StringUtils} from "./libraries/StringUtils.sol"; 10 | import {Base64} from "./libraries/Base64.sol"; 11 | 12 | /** 13 | * @title Domains 14 | * @notice - Contract that creates and stores domains in the blockchain. 15 | * @dev - It inherits from `ERC721URIStorage`. 16 | */ 17 | contract Domains is ERC721URIStorage { 18 | using Counters for Counters.Counter; 19 | Counters.Counter private _tokenIds; 20 | 21 | /** 22 | * @notice - Who deployed the contract. 23 | */ 24 | address public owner; 25 | 26 | /** 27 | * @notice - Stores the domain's TLD. 28 | */ 29 | string public tld; 30 | 31 | string svgPartOne = 32 | ''; 33 | string svgPartTwo = ""; 34 | 35 | /** 36 | * @notice - Stores addresses of the owners of all the domains, indexed by domain's name. 37 | */ 38 | mapping(string => address) public domains; 39 | 40 | /** 41 | * @notice - Stores all the domains' names, indexed by token ID. 42 | */ 43 | mapping(uint256 => string) public names; 44 | 45 | /** 46 | * @notice - Stores records for domains, indexed by domain's name. 47 | */ 48 | mapping(string => string) public records; 49 | 50 | /** 51 | * @dev - Sets the value of `owner` to who's deploying the contract, `tld` to the param `_tld_` and logs it to the console. 52 | * @param _tld - The value to be set for `tld`. 53 | */ 54 | constructor(string memory _tld) 55 | payable 56 | ERC721("Zed Run Name Service", "ZNS") 57 | { 58 | owner = payable(msg.sender); 59 | tld = _tld; 60 | console.log("%s name service deployed", _tld); 61 | } 62 | 63 | /** 64 | * @notice - Gives the price of a domain based on its name's length. 65 | * @param name - The name for the domain to be registered. 66 | * @return - The price for that domain. 67 | */ 68 | function getPrice(string calldata name) public pure returns (uint256) { 69 | uint256 len = StringUtils.strlen(name); 70 | require(len > 0); 71 | if (len == 3) { 72 | return 5 * 10**17; // 0.5 MATIC 73 | } else if (len == 4) { 74 | return 3 * 10**17; 75 | } else { 76 | return 1 * 10**17; 77 | } 78 | } 79 | 80 | /** 81 | * @dev - Requires the caller to be the contract's owner. 82 | * @param name - The name for the domain to be validated. 83 | */ 84 | modifier isValidName(string calldata name) { 85 | require( 86 | StringUtils.strlen(name) >= 3 && StringUtils.strlen(name) <= 10, 87 | "Names can have between 3 and 10 chars" 88 | ); 89 | _; 90 | } 91 | 92 | /** 93 | * @notice - Registers a domain name after checking it's valid, mapping it to the caller's address. 94 | * @param name - The name for the domain to be registered. 95 | */ 96 | function register(string calldata name) public payable isValidName(name) { 97 | require(domains[name] == address(0), "Name is already in use"); 98 | 99 | uint256 _price = getPrice(name); 100 | 101 | require(msg.value >= _price, "Not enough MATIC paid"); 102 | 103 | // Combines the name passed into the function with the TLD 104 | string memory _name = string(abi.encodePacked(name, ".", tld)); 105 | // Creates the SVG for the NFT with the name 106 | string memory finalSvg = string( 107 | abi.encodePacked(svgPartOne, _name, svgPartTwo) 108 | ); 109 | uint256 newRecordId = _tokenIds.current(); 110 | uint256 length = StringUtils.strlen(name); 111 | string memory strLen = Strings.toString(length); 112 | 113 | console.log( 114 | "Registering %s.%s on the contract with tokenID %d", 115 | name, 116 | tld, 117 | newRecordId 118 | ); 119 | 120 | // Creates the JSON metadata of our NFT. We do this by combining strings and encoding as base64 121 | string memory json = Base64.encode( 122 | bytes( 123 | string( 124 | abi.encodePacked( 125 | '{"name": "', 126 | _name, 127 | '", "description": "A domain on the Ninja name service", "image": "data:image/svg+xml;base64,', 128 | Base64.encode(bytes(finalSvg)), 129 | '","length":"', 130 | strLen, 131 | '"}' 132 | ) 133 | ) 134 | ) 135 | ); 136 | 137 | string memory finalTokenUri = string( 138 | abi.encodePacked("data:application/json;base64,", json) 139 | ); 140 | 141 | console.log( 142 | "\n--------------------------------------------------------" 143 | ); 144 | console.log("Final tokenURI", finalTokenUri); 145 | console.log( 146 | "--------------------------------------------------------\n" 147 | ); 148 | 149 | _safeMint(msg.sender, newRecordId); 150 | _setTokenURI(newRecordId, finalTokenUri); 151 | 152 | domains[name] = msg.sender; 153 | names[newRecordId] = name; 154 | 155 | _tokenIds.increment(); 156 | } 157 | 158 | /** 159 | * @notice - Returns the address registered for a specific domain name. 160 | * @param name - The domain's name. 161 | * @return - The address registered for that domain. 162 | */ 163 | function getAddress(string calldata name) public view returns (address) { 164 | return domains[name]; 165 | } 166 | 167 | /** 168 | * @notice - Sets a record for a specific domain name. 169 | * @param name - The domain's name. 170 | * @param record - The record to store. 171 | */ 172 | function setRecord(string calldata name, string calldata record) public { 173 | require( 174 | domains[name] == msg.sender, 175 | "Only the owner of the domain can set a record" 176 | ); 177 | 178 | records[name] = record; 179 | } 180 | 181 | /** 182 | * @notice - Provides the record stored for a specific domain name. 183 | * @param name - The domain's name. 184 | * @return - The record stored in that domain. 185 | */ 186 | function getRecord(string calldata name) 187 | public 188 | view 189 | returns (string memory) 190 | { 191 | return records[name]; 192 | } 193 | 194 | /** 195 | * @notice - Provides a list of all the domain names. 196 | * @return - The list of all the domain names. 197 | */ 198 | function getAllNames() public view returns (string[] memory) { 199 | console.log("Getting all names from contract"); 200 | string[] memory allNames = new string[](_tokenIds.current()); 201 | for (uint256 i = 0; i < _tokenIds.current(); i++) { 202 | allNames[i] = names[i]; 203 | console.log("Name for token %d is %s", i, allNames[i]); 204 | } 205 | 206 | return allNames; 207 | } 208 | 209 | /** 210 | * @dev - Requires the caller to be the contract's owner. 211 | */ 212 | modifier onlyOwner() { 213 | require(msg.sender == owner); 214 | _; 215 | } 216 | 217 | /** 218 | * @notice - Withdraws the contract's balance, only valid for the owner. 219 | */ 220 | function withdraw() public onlyOwner { 221 | uint256 amount = address(this).balance; 222 | 223 | (bool success, ) = msg.sender.call{value: amount}(""); 224 | require(success, "Failed to withdraw Matic"); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/artifacts/contracts/Domains.sol/Domains.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Domains", 4 | "sourceName": "contracts/Domains.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "string", 10 | "name": "_tld", 11 | "type": "string" 12 | } 13 | ], 14 | "stateMutability": "payable", 15 | "type": "constructor" 16 | }, 17 | { 18 | "anonymous": false, 19 | "inputs": [ 20 | { 21 | "indexed": true, 22 | "internalType": "address", 23 | "name": "owner", 24 | "type": "address" 25 | }, 26 | { 27 | "indexed": true, 28 | "internalType": "address", 29 | "name": "approved", 30 | "type": "address" 31 | }, 32 | { 33 | "indexed": true, 34 | "internalType": "uint256", 35 | "name": "tokenId", 36 | "type": "uint256" 37 | } 38 | ], 39 | "name": "Approval", 40 | "type": "event" 41 | }, 42 | { 43 | "anonymous": false, 44 | "inputs": [ 45 | { 46 | "indexed": true, 47 | "internalType": "address", 48 | "name": "owner", 49 | "type": "address" 50 | }, 51 | { 52 | "indexed": true, 53 | "internalType": "address", 54 | "name": "operator", 55 | "type": "address" 56 | }, 57 | { 58 | "indexed": false, 59 | "internalType": "bool", 60 | "name": "approved", 61 | "type": "bool" 62 | } 63 | ], 64 | "name": "ApprovalForAll", 65 | "type": "event" 66 | }, 67 | { 68 | "anonymous": false, 69 | "inputs": [ 70 | { 71 | "indexed": true, 72 | "internalType": "address", 73 | "name": "from", 74 | "type": "address" 75 | }, 76 | { 77 | "indexed": true, 78 | "internalType": "address", 79 | "name": "to", 80 | "type": "address" 81 | }, 82 | { 83 | "indexed": true, 84 | "internalType": "uint256", 85 | "name": "tokenId", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "Transfer", 90 | "type": "event" 91 | }, 92 | { 93 | "inputs": [ 94 | { 95 | "internalType": "address", 96 | "name": "to", 97 | "type": "address" 98 | }, 99 | { 100 | "internalType": "uint256", 101 | "name": "tokenId", 102 | "type": "uint256" 103 | } 104 | ], 105 | "name": "approve", 106 | "outputs": [], 107 | "stateMutability": "nonpayable", 108 | "type": "function" 109 | }, 110 | { 111 | "inputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "owner", 115 | "type": "address" 116 | } 117 | ], 118 | "name": "balanceOf", 119 | "outputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "", 123 | "type": "uint256" 124 | } 125 | ], 126 | "stateMutability": "view", 127 | "type": "function" 128 | }, 129 | { 130 | "inputs": [ 131 | { 132 | "internalType": "string", 133 | "name": "", 134 | "type": "string" 135 | } 136 | ], 137 | "name": "domains", 138 | "outputs": [ 139 | { 140 | "internalType": "address", 141 | "name": "", 142 | "type": "address" 143 | } 144 | ], 145 | "stateMutability": "view", 146 | "type": "function" 147 | }, 148 | { 149 | "inputs": [ 150 | { 151 | "internalType": "string", 152 | "name": "name", 153 | "type": "string" 154 | } 155 | ], 156 | "name": "getAddress", 157 | "outputs": [ 158 | { 159 | "internalType": "address", 160 | "name": "", 161 | "type": "address" 162 | } 163 | ], 164 | "stateMutability": "view", 165 | "type": "function" 166 | }, 167 | { 168 | "inputs": [], 169 | "name": "getAllNames", 170 | "outputs": [ 171 | { 172 | "internalType": "string[]", 173 | "name": "", 174 | "type": "string[]" 175 | } 176 | ], 177 | "stateMutability": "view", 178 | "type": "function" 179 | }, 180 | { 181 | "inputs": [ 182 | { 183 | "internalType": "uint256", 184 | "name": "tokenId", 185 | "type": "uint256" 186 | } 187 | ], 188 | "name": "getApproved", 189 | "outputs": [ 190 | { 191 | "internalType": "address", 192 | "name": "", 193 | "type": "address" 194 | } 195 | ], 196 | "stateMutability": "view", 197 | "type": "function" 198 | }, 199 | { 200 | "inputs": [ 201 | { 202 | "internalType": "string", 203 | "name": "name", 204 | "type": "string" 205 | } 206 | ], 207 | "name": "getPrice", 208 | "outputs": [ 209 | { 210 | "internalType": "uint256", 211 | "name": "", 212 | "type": "uint256" 213 | } 214 | ], 215 | "stateMutability": "pure", 216 | "type": "function" 217 | }, 218 | { 219 | "inputs": [ 220 | { 221 | "internalType": "string", 222 | "name": "name", 223 | "type": "string" 224 | } 225 | ], 226 | "name": "getRecord", 227 | "outputs": [ 228 | { 229 | "internalType": "string", 230 | "name": "", 231 | "type": "string" 232 | } 233 | ], 234 | "stateMutability": "view", 235 | "type": "function" 236 | }, 237 | { 238 | "inputs": [ 239 | { 240 | "internalType": "address", 241 | "name": "owner", 242 | "type": "address" 243 | }, 244 | { 245 | "internalType": "address", 246 | "name": "operator", 247 | "type": "address" 248 | } 249 | ], 250 | "name": "isApprovedForAll", 251 | "outputs": [ 252 | { 253 | "internalType": "bool", 254 | "name": "", 255 | "type": "bool" 256 | } 257 | ], 258 | "stateMutability": "view", 259 | "type": "function" 260 | }, 261 | { 262 | "inputs": [], 263 | "name": "name", 264 | "outputs": [ 265 | { 266 | "internalType": "string", 267 | "name": "", 268 | "type": "string" 269 | } 270 | ], 271 | "stateMutability": "view", 272 | "type": "function" 273 | }, 274 | { 275 | "inputs": [ 276 | { 277 | "internalType": "uint256", 278 | "name": "", 279 | "type": "uint256" 280 | } 281 | ], 282 | "name": "names", 283 | "outputs": [ 284 | { 285 | "internalType": "string", 286 | "name": "", 287 | "type": "string" 288 | } 289 | ], 290 | "stateMutability": "view", 291 | "type": "function" 292 | }, 293 | { 294 | "inputs": [], 295 | "name": "owner", 296 | "outputs": [ 297 | { 298 | "internalType": "address", 299 | "name": "", 300 | "type": "address" 301 | } 302 | ], 303 | "stateMutability": "view", 304 | "type": "function" 305 | }, 306 | { 307 | "inputs": [ 308 | { 309 | "internalType": "uint256", 310 | "name": "tokenId", 311 | "type": "uint256" 312 | } 313 | ], 314 | "name": "ownerOf", 315 | "outputs": [ 316 | { 317 | "internalType": "address", 318 | "name": "", 319 | "type": "address" 320 | } 321 | ], 322 | "stateMutability": "view", 323 | "type": "function" 324 | }, 325 | { 326 | "inputs": [ 327 | { 328 | "internalType": "string", 329 | "name": "", 330 | "type": "string" 331 | } 332 | ], 333 | "name": "records", 334 | "outputs": [ 335 | { 336 | "internalType": "string", 337 | "name": "", 338 | "type": "string" 339 | } 340 | ], 341 | "stateMutability": "view", 342 | "type": "function" 343 | }, 344 | { 345 | "inputs": [ 346 | { 347 | "internalType": "string", 348 | "name": "name", 349 | "type": "string" 350 | } 351 | ], 352 | "name": "register", 353 | "outputs": [], 354 | "stateMutability": "payable", 355 | "type": "function" 356 | }, 357 | { 358 | "inputs": [ 359 | { 360 | "internalType": "address", 361 | "name": "from", 362 | "type": "address" 363 | }, 364 | { 365 | "internalType": "address", 366 | "name": "to", 367 | "type": "address" 368 | }, 369 | { 370 | "internalType": "uint256", 371 | "name": "tokenId", 372 | "type": "uint256" 373 | } 374 | ], 375 | "name": "safeTransferFrom", 376 | "outputs": [], 377 | "stateMutability": "nonpayable", 378 | "type": "function" 379 | }, 380 | { 381 | "inputs": [ 382 | { 383 | "internalType": "address", 384 | "name": "from", 385 | "type": "address" 386 | }, 387 | { 388 | "internalType": "address", 389 | "name": "to", 390 | "type": "address" 391 | }, 392 | { 393 | "internalType": "uint256", 394 | "name": "tokenId", 395 | "type": "uint256" 396 | }, 397 | { 398 | "internalType": "bytes", 399 | "name": "_data", 400 | "type": "bytes" 401 | } 402 | ], 403 | "name": "safeTransferFrom", 404 | "outputs": [], 405 | "stateMutability": "nonpayable", 406 | "type": "function" 407 | }, 408 | { 409 | "inputs": [ 410 | { 411 | "internalType": "address", 412 | "name": "operator", 413 | "type": "address" 414 | }, 415 | { 416 | "internalType": "bool", 417 | "name": "approved", 418 | "type": "bool" 419 | } 420 | ], 421 | "name": "setApprovalForAll", 422 | "outputs": [], 423 | "stateMutability": "nonpayable", 424 | "type": "function" 425 | }, 426 | { 427 | "inputs": [ 428 | { 429 | "internalType": "string", 430 | "name": "name", 431 | "type": "string" 432 | }, 433 | { 434 | "internalType": "string", 435 | "name": "record", 436 | "type": "string" 437 | } 438 | ], 439 | "name": "setRecord", 440 | "outputs": [], 441 | "stateMutability": "nonpayable", 442 | "type": "function" 443 | }, 444 | { 445 | "inputs": [ 446 | { 447 | "internalType": "bytes4", 448 | "name": "interfaceId", 449 | "type": "bytes4" 450 | } 451 | ], 452 | "name": "supportsInterface", 453 | "outputs": [ 454 | { 455 | "internalType": "bool", 456 | "name": "", 457 | "type": "bool" 458 | } 459 | ], 460 | "stateMutability": "view", 461 | "type": "function" 462 | }, 463 | { 464 | "inputs": [], 465 | "name": "symbol", 466 | "outputs": [ 467 | { 468 | "internalType": "string", 469 | "name": "", 470 | "type": "string" 471 | } 472 | ], 473 | "stateMutability": "view", 474 | "type": "function" 475 | }, 476 | { 477 | "inputs": [], 478 | "name": "tld", 479 | "outputs": [ 480 | { 481 | "internalType": "string", 482 | "name": "", 483 | "type": "string" 484 | } 485 | ], 486 | "stateMutability": "view", 487 | "type": "function" 488 | }, 489 | { 490 | "inputs": [ 491 | { 492 | "internalType": "uint256", 493 | "name": "tokenId", 494 | "type": "uint256" 495 | } 496 | ], 497 | "name": "tokenURI", 498 | "outputs": [ 499 | { 500 | "internalType": "string", 501 | "name": "", 502 | "type": "string" 503 | } 504 | ], 505 | "stateMutability": "view", 506 | "type": "function" 507 | }, 508 | { 509 | "inputs": [ 510 | { 511 | "internalType": "address", 512 | "name": "from", 513 | "type": "address" 514 | }, 515 | { 516 | "internalType": "address", 517 | "name": "to", 518 | "type": "address" 519 | }, 520 | { 521 | "internalType": "uint256", 522 | "name": "tokenId", 523 | "type": "uint256" 524 | } 525 | ], 526 | "name": "transferFrom", 527 | "outputs": [], 528 | "stateMutability": "nonpayable", 529 | "type": "function" 530 | }, 531 | { 532 | "inputs": [], 533 | "name": "withdraw", 534 | "outputs": [], 535 | "stateMutability": "nonpayable", 536 | "type": "function" 537 | } 538 | ], 539 | "bytecode": "0x6080604052604051806107a0016040528061076c8152602001620053e861076c9139600a908051906020019062000038929190620002c8565b506040518060400160405280600d81526020017f3c2f746578743e3c2f7376673e00000000000000000000000000000000000000815250600b908051906020019062000086929190620002c8565b5060405162005b5438038062005b548339818101604052810190620000ac919062000515565b6040518060400160405280601481526020017f5a65642052756e204e616d6520536572766963650000000000000000000000008152506040518060400160405280600381526020017f5a4e530000000000000000000000000000000000000000000000000000000000815250816000908051906020019062000130929190620002c8565b50806001908051906020019062000149929190620002c8565b50505033600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060099080519060200190620001a5929190620002c8565b50620001f26040518060400160405280601881526020017f2573206e616d652073657276696365206465706c6f796564000000000000000081525082620001f960201b62001b211760201c565b5062000663565b6200029b828260405160240162000212929190620005c3565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506200029f60201b60201c565b5050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b828054620002d6906200062d565b90600052602060002090601f016020900481019282620002fa576000855562000346565b82601f106200031557805160ff191683800117855562000346565b8280016001018555821562000346579182015b828111156200034557825182559160200191906001019062000328565b5b50905062000355919062000359565b5090565b5b80821115620003745760008160009055506001016200035a565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620003e18262000396565b810181811067ffffffffffffffff82111715620004035762000402620003a7565b5b80604052505050565b60006200041862000378565b9050620004268282620003d6565b919050565b600067ffffffffffffffff821115620004495762000448620003a7565b5b620004548262000396565b9050602081019050919050565b60005b838110156200048157808201518184015260208101905062000464565b8381111562000491576000848401525b50505050565b6000620004ae620004a8846200042b565b6200040c565b905082815260208101848484011115620004cd57620004cc62000391565b5b620004da84828562000461565b509392505050565b600082601f830112620004fa57620004f96200038c565b5b81516200050c84826020860162000497565b91505092915050565b6000602082840312156200052e576200052d62000382565b5b600082015167ffffffffffffffff8111156200054f576200054e62000387565b5b6200055d84828501620004e2565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60006200058f8262000566565b6200059b818562000571565b9350620005ad81856020860162000461565b620005b88162000396565b840191505092915050565b60006040820190508181036000830152620005df818562000582565b90508181036020830152620005f5818462000582565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200064657607f821691505b602082108114156200065d576200065c620005fe565b5b50919050565b614d7580620006736000396000f3fe6080604052600436106101665760003560e01c8063541e771d116100d1578063b88d4fde1161008a578063c87b56dd11610064578063c87b56dd14610586578063e985e9c5146105c3578063f2c298be14610600578063fb825e5f1461061c57610166565b8063b88d4fde146104f7578063bf40fac114610520578063c1880a981461055d57610166565b8063541e771d146103c15780636352211e146103fe57806370a082311461043b5780638da5cb5b1461047857806395d89b41146104a3578063a22cb465146104ce57610166565b80632644923511610123578063264492351461029f5780632d551432146102dc5780633ccfd60b1461030757806342842e0e1461031e5780634622ab0314610347578063524f38891461038457610166565b806301ffc9a71461016b57806306fdde03146101a8578063081812fc146101d3578063095ea7b31461021057806311dd88451461023957806323b872dd14610276575b600080fd5b34801561017757600080fd5b50610192600480360381019061018d9190613006565b610647565b60405161019f919061304e565b60405180910390f35b3480156101b457600080fd5b506101bd610729565b6040516101ca9190613102565b60405180910390f35b3480156101df57600080fd5b506101fa60048036038101906101f5919061315a565b6107bb565b60405161020791906131c8565b60405180910390f35b34801561021c57600080fd5b506102376004803603810190610232919061320f565b610840565b005b34801561024557600080fd5b50610260600480360381019061025b91906132b4565b610958565b60405161026d9190613102565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190613301565b610a0b565b005b3480156102ab57600080fd5b506102c660048036038101906102c19190613484565b610a6b565b6040516102d391906131c8565b60405180910390f35b3480156102e857600080fd5b506102f1610ab4565b6040516102fe9190613102565b60405180910390f35b34801561031357600080fd5b5061031c610b42565b005b34801561032a57600080fd5b5061034560048036038101906103409190613301565b610c51565b005b34801561035357600080fd5b5061036e6004803603810190610369919061315a565b610c71565b60405161037b9190613102565b60405180910390f35b34801561039057600080fd5b506103ab60048036038101906103a691906132b4565b610d11565b6040516103b891906134dc565b60405180910390f35b3480156103cd57600080fd5b506103e860048036038101906103e39190613484565b610db7565b6040516103f59190613102565b60405180910390f35b34801561040a57600080fd5b506104256004803603810190610420919061315a565b610e6d565b60405161043291906131c8565b60405180910390f35b34801561044757600080fd5b50610462600480360381019061045d91906134f7565b610f1f565b60405161046f91906134dc565b60405180910390f35b34801561048457600080fd5b5061048d610fd7565b60405161049a91906131c8565b60405180910390f35b3480156104af57600080fd5b506104b8610ffd565b6040516104c59190613102565b60405180910390f35b3480156104da57600080fd5b506104f560048036038101906104f09190613550565b61108f565b005b34801561050357600080fd5b5061051e60048036038101906105199190613631565b6110a5565b005b34801561052c57600080fd5b50610547600480360381019061054291906132b4565b611107565b60405161055491906131c8565b60405180910390f35b34801561056957600080fd5b50610584600480360381019061057f91906136b4565b611152565b005b34801561059257600080fd5b506105ad60048036038101906105a8919061315a565b611236565b6040516105ba9190613102565b60405180910390f35b3480156105cf57600080fd5b506105ea60048036038101906105e59190613735565b611388565b6040516105f7919061304e565b60405180910390f35b61061a600480360381019061061591906132b4565b61141c565b005b34801561062857600080fd5b50610631611943565b60405161063e9190613881565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061071257507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610722575061072182611bbd565b5b9050919050565b606060008054610738906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610764906138d2565b80156107b15780601f10610786576101008083540402835291602001916107b1565b820191906000526020600020905b81548152906001019060200180831161079457829003601f168201915b5050505050905090565b60006107c682611c27565b610805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fc90613976565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061084b82610e6d565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156108bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b390613a08565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166108db611c93565b73ffffffffffffffffffffffffffffffffffffffff16148061090a575061090981610904611c93565b611388565b5b610949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094090613a9a565b60405180910390fd5b6109538383611c9b565b505050565b6060600e838360405161096c929190613aea565b90815260200160405180910390208054610985906138d2565b80601f01602080910402602001604051908101604052809291908181526020018280546109b1906138d2565b80156109fe5780601f106109d3576101008083540402835291602001916109fe565b820191906000526020600020905b8154815290600101906020018083116109e157829003601f168201915b5050505050905092915050565b610a1c610a16611c93565b82611d54565b610a5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5290613b75565b60405180910390fd5b610a66838383611e32565b505050565b600c818051602081018201805184825260208301602085012081835280955050505050506000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60098054610ac1906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610aed906138d2565b8015610b3a5780601f10610b0f57610100808354040283529160200191610b3a565b820191906000526020600020905b815481529060010190602001808311610b1d57829003601f168201915b505050505081565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b9c57600080fd5b600047905060003373ffffffffffffffffffffffffffffffffffffffff1682604051610bc790613bc6565b60006040518083038185875af1925050503d8060008114610c04576040519150601f19603f3d011682016040523d82523d6000602084013e610c09565b606091505b5050905080610c4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4490613c27565b60405180910390fd5b5050565b610c6c838383604051806020016040528060008152506110a5565b505050565b600d6020528060005260406000206000915090508054610c90906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610cbc906138d2565b8015610d095780601f10610cde57610100808354040283529160200191610d09565b820191906000526020600020905b815481529060010190602001808311610cec57829003601f168201915b505050505081565b600080610d6184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b905060008111610d7057600080fd5b6003811415610d8a576706f05b59d3b20000915050610db1565b6004811415610da457670429d069189e0000915050610db1565b67016345785d8a00009150505b92915050565b600e818051602081018201805184825260208301602085012081835280955050505050506000915090508054610dec906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e18906138d2565b8015610e655780601f10610e3a57610100808354040283529160200191610e65565b820191906000526020600020905b815481529060010190602001808311610e4857829003601f168201915b505050505081565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0d90613cb9565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8790613d4b565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461100c906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611038906138d2565b80156110855780601f1061105a57610100808354040283529160200191611085565b820191906000526020600020905b81548152906001019060200180831161106857829003601f168201915b5050505050905090565b6110a161109a611c93565b838361224e565b5050565b6110b66110b0611c93565b83611d54565b6110f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ec90613b75565b60405180910390fd5b611101848484846123bb565b50505050565b6000600c838360405161111b929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905092915050565b3373ffffffffffffffffffffffffffffffffffffffff16600c858560405161117b929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f790613ddd565b60405180910390fd5b8181600e8686604051611214929190613aea565b9081526020016040518091039020919061122f929190612e71565b5050505050565b606061124182611c27565b611280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127790613e6f565b60405180910390fd5b60006006600084815260200190815260200160002080546112a0906138d2565b80601f01602080910402602001604051908101604052809291908181526020018280546112cc906138d2565b80156113195780601f106112ee57610100808354040283529160200191611319565b820191906000526020600020905b8154815290600101906020018083116112fc57829003601f168201915b50505050509050600061132a612417565b9050600081511415611340578192505050611383565b60008251111561137557808260405160200161135d929190613ec0565b60405160208183030381529060405292505050611383565b61137e8461242e565b925050505b919050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8181600361146d83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b101580156114c85750600a6114c583838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b11155b611507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114fe90613f56565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600c8585604051611531929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ad90613fc2565b60405180910390fd5b60006115c28585610d11565b905080341015611607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115fe9061402e565b60405180910390fd5b60008585600960405160200161161f9392919061412e565b60405160208183030381529060405290506000600a82600b6040516020016116499392919061415f565b6040516020818303038152906040529050600061166660076124d5565b905060006116b789898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b905060006116c4826124e3565b90506117b8604051806060016040528060318152602001614c96603191398b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060098054611734906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611760906138d2565b80156117ad5780601f10611782576101008083540402835291602001916117ad565b820191906000526020600020905b81548152906001019060200180831161179057829003601f168201915b505050505086612644565b60006117ee866117c7876126e6565b846040516020016117da9392919061430c565b6040516020818303038152906040526126e6565b905060008160405160200161180391906143b5565b6040516020818303038152906040529050611835604051806060016040528060398152602001614c5d6039913961287e565b6118746040518060400160405280600e81526020017f46696e616c20746f6b656e55524900000000000000000000000000000000000081525082611b21565b611895604051806060016040528060398152602001614cc76039913961287e565b61189f3386612917565b6118a98582612935565b33600c8d8d6040516118bc929190613aea565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b8b600d6000888152602001908152602001600020919061192a929190612e71565b5061193560076129a9565b505050505050505050505050565b60606119836040518060400160405280601f81526020017f47657474696e6720616c6c206e616d65732066726f6d20636f6e74726163740081525061287e565b600061198f60076124d5565b67ffffffffffffffff8111156119a8576119a7613359565b5b6040519080825280602002602001820160405280156119db57816020015b60608152602001906001900390816119c65790505b50905060005b6119eb60076124d5565b811015611b1957600d60008281526020019081526020016000208054611a10906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611a3c906138d2565b8015611a895780601f10611a5e57610100808354040283529160200191611a89565b820191906000526020600020905b815481529060010190602001808311611a6c57829003601f168201915b5050505050828281518110611aa157611aa06143d7565b5b6020026020010181905250611b066040518060400160405280601781526020017f4e616d6520666f7220746f6b656e20256420697320257300000000000000000081525082848481518110611af957611af86143d7565b5b60200260200101516129bf565b8080611b1190614435565b9150506119e1565b508091505090565b611bb98282604051602401611b3792919061447e565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611d0e83610e6d565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611d5f82611c27565b611d9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9590614527565b60405180910390fd5b6000611da983610e6d565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611e1857508373ffffffffffffffffffffffffffffffffffffffff16611e00846107bb565b73ffffffffffffffffffffffffffffffffffffffff16145b80611e295750611e288185611388565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611e5282610e6d565b73ffffffffffffffffffffffffffffffffffffffff1614611ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9f906145b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0f9061464b565b60405180910390fd5b611f23838383612a87565b611f2e600082611c9b565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611f7e919061466b565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611fd5919061469f565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612094838383612a8c565b505050565b60008060008084519050600092505b808210156122435760008583815181106120c5576120c46143d7565b5b602001015160f81c60f81b9050608060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121145760018361210d919061469f565b925061222f565b60e060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121565760028361214f919061469f565b925061222e565b60f060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916101561219857600383612191919061469f565b925061222d565b60f8801b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121d9576004836121d2919061469f565b925061222c565b60fc60f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916101561221b57600583612214919061469f565b925061222b565b600683612228919061469f565b92505b5b5b5b5b50828061223b90614435565b9350506120a8565b829350505050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156122bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b490614741565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516123ae919061304e565b60405180910390a3505050565b6123c6848484611e32565b6123d284848484612a91565b612411576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612408906147d3565b60405180910390fd5b50505050565b606060405180602001604052806000815250905090565b606061243982611c27565b612478576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246f90614865565b60405180910390fd5b6000612482612417565b905060008151116124a257604051806020016040528060008152506124cd565b806124ac846124e3565b6040516020016124bd929190613ec0565b6040516020818303038152906040525b915050919050565b600081600001549050919050565b6060600082141561252b576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061263f565b600082905060005b6000821461255d57808061254690614435565b915050600a8261255691906148b4565b9150612533565b60008167ffffffffffffffff81111561257957612578613359565b5b6040519080825280601f01601f1916602001820160405280156125ab5781602001600182028036833780820191505090505b5090505b60008514612638576001826125c4919061466b565b9150600a856125d391906148e5565b60306125df919061469f565b60f81b8183815181106125f5576125f46143d7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561263191906148b4565b94506125af565b8093505050505b919050565b6126e08484848460405160240161265e9493929190614916565b6040516020818303038152906040527f9fd009f5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b50505050565b6060600082519050600081141561270f5760405180602001604052806000815250915050612879565b60006003600283612720919061469f565b61272a91906148b4565b60046127369190614970565b90506000602082612747919061469f565b67ffffffffffffffff8111156127605761275f613359565b5b6040519080825280601f01601f1916602001820160405280156127925781602001600182028036833780820191505090505b5090506000604051806060016040528060408152602001614d00604091399050600181016020830160005b868110156128365760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506127bd565b50600386066001811461285057600281146128605761286b565b613d3d60f01b600283035261286b565b603d60f81b60018303525b508484525050819450505050505b919050565b612914816040516024016128929190613102565b6040516020818303038152906040527f41304fac000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b50565b612931828260405180602001604052806000815250612c19565b5050565b61293e82611c27565b61297d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297490614a3c565b60405180910390fd5b806006600084815260200190815260200160002090805190602001906129a4929190612ef7565b505050565b6001816000016000828254019250508190555050565b612a598383836040516024016129d793929190614a5c565b6040516020818303038152906040527fa3f5c739000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b505050565b505050565b6000612ab28473ffffffffffffffffffffffffffffffffffffffff16612c74565b15612c0c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612adb611c93565b8786866040518563ffffffff1660e01b8152600401612afd9493929190614af6565b6020604051808303816000875af1925050508015612b3957506040513d601f19601f82011682018060405250810190612b369190614b57565b60015b612bbc573d8060008114612b69576040519150601f19603f3d011682016040523d82523d6000602084013e612b6e565b606091505b50600081511415612bb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bab906147d3565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612c11565b600190505b949350505050565b612c238383612c97565b612c306000848484612a91565b612c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c66906147d3565b60405180910390fd5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612d07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cfe90614bd0565b60405180910390fd5b612d1081611c27565b15612d50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4790614c3c565b60405180910390fd5b612d5c60008383612a87565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612dac919061469f565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612e6d60008383612a8c565b5050565b828054612e7d906138d2565b90600052602060002090601f016020900481019282612e9f5760008555612ee6565b82601f10612eb857803560ff1916838001178555612ee6565b82800160010185558215612ee6579182015b82811115612ee5578235825591602001919060010190612eca565b5b509050612ef39190612f7d565b5090565b828054612f03906138d2565b90600052602060002090601f016020900481019282612f255760008555612f6c565b82601f10612f3e57805160ff1916838001178555612f6c565b82800160010185558215612f6c579182015b82811115612f6b578251825591602001919060010190612f50565b5b509050612f799190612f7d565b5090565b5b80821115612f96576000816000905550600101612f7e565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fe381612fae565b8114612fee57600080fd5b50565b60008135905061300081612fda565b92915050565b60006020828403121561301c5761301b612fa4565b5b600061302a84828501612ff1565b91505092915050565b60008115159050919050565b61304881613033565b82525050565b6000602082019050613063600083018461303f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156130a3578082015181840152602081019050613088565b838111156130b2576000848401525b50505050565b6000601f19601f8301169050919050565b60006130d482613069565b6130de8185613074565b93506130ee818560208601613085565b6130f7816130b8565b840191505092915050565b6000602082019050818103600083015261311c81846130c9565b905092915050565b6000819050919050565b61313781613124565b811461314257600080fd5b50565b6000813590506131548161312e565b92915050565b6000602082840312156131705761316f612fa4565b5b600061317e84828501613145565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006131b282613187565b9050919050565b6131c2816131a7565b82525050565b60006020820190506131dd60008301846131b9565b92915050565b6131ec816131a7565b81146131f757600080fd5b50565b600081359050613209816131e3565b92915050565b6000806040838503121561322657613225612fa4565b5b6000613234858286016131fa565b925050602061324585828601613145565b9150509250929050565b600080fd5b600080fd5b600080fd5b60008083601f8401126132745761327361324f565b5b8235905067ffffffffffffffff81111561329157613290613254565b5b6020830191508360018202830111156132ad576132ac613259565b5b9250929050565b600080602083850312156132cb576132ca612fa4565b5b600083013567ffffffffffffffff8111156132e9576132e8612fa9565b5b6132f58582860161325e565b92509250509250929050565b60008060006060848603121561331a57613319612fa4565b5b6000613328868287016131fa565b9350506020613339868287016131fa565b925050604061334a86828701613145565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613391826130b8565b810181811067ffffffffffffffff821117156133b0576133af613359565b5b80604052505050565b60006133c3612f9a565b90506133cf8282613388565b919050565b600067ffffffffffffffff8211156133ef576133ee613359565b5b6133f8826130b8565b9050602081019050919050565b82818337600083830152505050565b6000613427613422846133d4565b6133b9565b90508281526020810184848401111561344357613442613354565b5b61344e848285613405565b509392505050565b600082601f83011261346b5761346a61324f565b5b813561347b848260208601613414565b91505092915050565b60006020828403121561349a57613499612fa4565b5b600082013567ffffffffffffffff8111156134b8576134b7612fa9565b5b6134c484828501613456565b91505092915050565b6134d681613124565b82525050565b60006020820190506134f160008301846134cd565b92915050565b60006020828403121561350d5761350c612fa4565b5b600061351b848285016131fa565b91505092915050565b61352d81613033565b811461353857600080fd5b50565b60008135905061354a81613524565b92915050565b6000806040838503121561356757613566612fa4565b5b6000613575858286016131fa565b92505060206135868582860161353b565b9150509250929050565b600067ffffffffffffffff8211156135ab576135aa613359565b5b6135b4826130b8565b9050602081019050919050565b60006135d46135cf84613590565b6133b9565b9050828152602081018484840111156135f0576135ef613354565b5b6135fb848285613405565b509392505050565b600082601f8301126136185761361761324f565b5b81356136288482602086016135c1565b91505092915050565b6000806000806080858703121561364b5761364a612fa4565b5b6000613659878288016131fa565b945050602061366a878288016131fa565b935050604061367b87828801613145565b925050606085013567ffffffffffffffff81111561369c5761369b612fa9565b5b6136a887828801613603565b91505092959194509250565b600080600080604085870312156136ce576136cd612fa4565b5b600085013567ffffffffffffffff8111156136ec576136eb612fa9565b5b6136f88782880161325e565b9450945050602085013567ffffffffffffffff81111561371b5761371a612fa9565b5b6137278782880161325e565b925092505092959194509250565b6000806040838503121561374c5761374b612fa4565b5b600061375a858286016131fa565b925050602061376b858286016131fa565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b60006137bd82613069565b6137c781856137a1565b93506137d7818560208601613085565b6137e0816130b8565b840191505092915050565b60006137f783836137b2565b905092915050565b6000602082019050919050565b600061381782613775565b6138218185613780565b93508360208202850161383385613791565b8060005b8581101561386f578484038952815161385085826137eb565b945061385b836137ff565b925060208a01995050600181019050613837565b50829750879550505050505092915050565b6000602082019050818103600083015261389b818461380c565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806138ea57607f821691505b602082108114156138fe576138fd6138a3565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000613960602c83613074565b915061396b82613904565b604082019050919050565b6000602082019050818103600083015261398f81613953565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006139f2602183613074565b91506139fd82613996565b604082019050919050565b60006020820190508181036000830152613a21816139e5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b6000613a84603883613074565b9150613a8f82613a28565b604082019050919050565b60006020820190508181036000830152613ab381613a77565b9050919050565b600081905092915050565b6000613ad18385613aba565b9350613ade838584613405565b82840190509392505050565b6000613af7828486613ac5565b91508190509392505050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b6000613b5f603183613074565b9150613b6a82613b03565b604082019050919050565b60006020820190508181036000830152613b8e81613b52565b9050919050565b600081905092915050565b50565b6000613bb0600083613b95565b9150613bbb82613ba0565b600082019050919050565b6000613bd182613ba3565b9150819050919050565b7f4661696c656420746f207769746864726177204d617469630000000000000000600082015250565b6000613c11601883613074565b9150613c1c82613bdb565b602082019050919050565b60006020820190508181036000830152613c4081613c04565b9050919050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000613ca3602983613074565b9150613cae82613c47565b604082019050919050565b60006020820190508181036000830152613cd281613c96565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000613d35602a83613074565b9150613d4082613cd9565b604082019050919050565b60006020820190508181036000830152613d6481613d28565b9050919050565b7f4f6e6c7920746865206f776e6572206f662074686520646f6d61696e2063616e60008201527f207365742061207265636f726400000000000000000000000000000000000000602082015250565b6000613dc7602d83613074565b9150613dd282613d6b565b604082019050919050565b60006020820190508181036000830152613df681613dba565b9050919050565b7f45524337323155524953746f726167653a2055524920717565727920666f722060008201527f6e6f6e6578697374656e7420746f6b656e000000000000000000000000000000602082015250565b6000613e59603183613074565b9150613e6482613dfd565b604082019050919050565b60006020820190508181036000830152613e8881613e4c565b9050919050565b6000613e9a82613069565b613ea48185613aba565b9350613eb4818560208601613085565b80840191505092915050565b6000613ecc8285613e8f565b9150613ed88284613e8f565b91508190509392505050565b7f4e616d65732063616e2068617665206265747765656e203320616e642031302060008201527f6368617273000000000000000000000000000000000000000000000000000000602082015250565b6000613f40602583613074565b9150613f4b82613ee4565b604082019050919050565b60006020820190508181036000830152613f6f81613f33565b9050919050565b7f4e616d6520697320616c726561647920696e2075736500000000000000000000600082015250565b6000613fac601683613074565b9150613fb782613f76565b602082019050919050565b60006020820190508181036000830152613fdb81613f9f565b9050919050565b7f4e6f7420656e6f756768204d4154494320706169640000000000000000000000600082015250565b6000614018601583613074565b915061402382613fe2565b602082019050919050565b600060208201905081810360008301526140478161400b565b9050919050565b7f2e00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614084600183613aba565b915061408f8261404e565b600182019050919050565b60008190508160005260206000209050919050565b600081546140bc816138d2565b6140c68186613aba565b945060018216600081146140e157600181146140f257614125565b60ff19831686528186019350614125565b6140fb8561409a565b60005b8381101561411d578154818901526001820191506020810190506140fe565b838801955050505b50505092915050565b600061413b828587613ac5565b915061414682614077565b915061415282846140af565b9150819050949350505050565b600061416b82866140af565b91506141778285613e8f565b915061418382846140af565b9150819050949350505050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000600082015250565b60006141c6600a83613aba565b91506141d182614190565b600a82019050919050565b7f222c20226465736372697074696f6e223a20224120646f6d61696e206f6e207460008201527f6865204e696e6a61206e616d652073657276696365222c2022696d616765223a60208201527f2022646174613a696d6167652f7376672b786d6c3b6261736536342c00000000604082015250565b600061425e605c83613aba565b9150614269826141dc565b605c82019050919050565b7f222c226c656e677468223a220000000000000000000000000000000000000000600082015250565b60006142aa600c83613aba565b91506142b582614274565b600c82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b60006142f6600283613aba565b9150614301826142c0565b600282019050919050565b6000614317826141b9565b91506143238286613e8f565b915061432e82614251565b915061433a8285613e8f565b91506143458261429d565b91506143518284613e8f565b915061435c826142e9565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061439f601d83613aba565b91506143aa82614369565b601d82019050919050565b60006143c082614392565b91506143cc8284613e8f565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061444082613124565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561447357614472614406565b5b600182019050919050565b6000604082019050818103600083015261449881856130c9565b905081810360208301526144ac81846130c9565b90509392505050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614511602c83613074565b915061451c826144b5565b604082019050919050565b6000602082019050818103600083015261454081614504565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006145a3602583613074565b91506145ae82614547565b604082019050919050565b600060208201905081810360008301526145d281614596565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614635602483613074565b9150614640826145d9565b604082019050919050565b6000602082019050818103600083015261466481614628565b9050919050565b600061467682613124565b915061468183613124565b92508282101561469457614693614406565b5b828203905092915050565b60006146aa82613124565b91506146b583613124565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156146ea576146e9614406565b5b828201905092915050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b600061472b601983613074565b9150614736826146f5565b602082019050919050565b6000602082019050818103600083015261475a8161471e565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b60006147bd603283613074565b91506147c882614761565b604082019050919050565b600060208201905081810360008301526147ec816147b0565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b600061484f602f83613074565b915061485a826147f3565b604082019050919050565b6000602082019050818103600083015261487e81614842565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148bf82613124565b91506148ca83613124565b9250826148da576148d9614885565b5b828204905092915050565b60006148f082613124565b91506148fb83613124565b92508261490b5761490a614885565b5b828206905092915050565b6000608082019050818103600083015261493081876130c9565b9050818103602083015261494481866130c9565b9050818103604083015261495881856130c9565b905061496760608301846134cd565b95945050505050565b600061497b82613124565b915061498683613124565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156149bf576149be614406565b5b828202905092915050565b7f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60008201527f6578697374656e7420746f6b656e000000000000000000000000000000000000602082015250565b6000614a26602e83613074565b9150614a31826149ca565b604082019050919050565b60006020820190508181036000830152614a5581614a19565b9050919050565b60006060820190508181036000830152614a7681866130c9565b9050614a8560208301856134cd565b8181036040830152614a9781846130c9565b9050949350505050565b600081519050919050565b600082825260208201905092915050565b6000614ac882614aa1565b614ad28185614aac565b9350614ae2818560208601613085565b614aeb816130b8565b840191505092915050565b6000608082019050614b0b60008301876131b9565b614b1860208301866131b9565b614b2560408301856134cd565b8181036060830152614b378184614abd565b905095945050505050565b600081519050614b5181612fda565b92915050565b600060208284031215614b6d57614b6c612fa4565b5b6000614b7b84828501614b42565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614bba602083613074565b9150614bc582614b84565b602082019050919050565b60006020820190508181036000830152614be981614bad565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614c26601c83613074565b9150614c3182614bf0565b602082019050919050565b60006020820190508181036000830152614c5581614c19565b905091905056fe0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d5265676973746572696e672025732e2573206f6e2074686520636f6e7472616374207769746820746f6b656e49442025642d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0a4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220f34ae7380f9822c278ead0324dee89e34ba7d535e8d05183ad425e34b68f48ba64736f6c634300080a00333c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667222077696474683d2232373022206865696768743d22323730222066696c6c3d226e6f6e65223e3c706174682066696c6c3d2275726c282361292220643d224d302030683237307632373048307a222f3e3c646566733e3c66696c7465722069643d22622220636f6c6f722d696e746572706f6c6174696f6e2d66696c746572733d2273524742222066696c746572556e6974733d227573657253706163654f6e55736522206865696768743d22323730222077696474683d22323730223e3c666544726f70536861646f772064783d2230222064793d22312220737464446576696174696f6e3d22322220666c6f6f642d6f7061636974793d222e323235222077696474683d223230302522206865696768743d2232303025222f3e3c2f66696c7465723e3c2f646566733e3c7061746820643d224d37322e3836332034322e39343961342e33383220342e3338322030203020302d342e33393420306c2d31302e30383120362e3033322d362e383520332e3933342d31302e30383120362e30333261342e33383220342e3338322030203020312d342e33393420306c2d382e3031332d342e37323161342e353220342e35322030203020312d312e3538392d312e36313620342e353420342e35342030203020312d2e3630382d322e313837762d392e333161342e323720342e3237203020302031202e3537322d322e32303820342e323520342e323520302030203120312e3632352d312e3539356c372e3838342d342e353961342e33383220342e33383220302030203120342e33393420306c372e38383420342e353961342e353220342e353220302030203120312e35383920312e36313620342e353420342e3534203020302031202e36303820322e31383776362e3033326c362e38352d342e303635762d362e30333261342e323720342e32372030203020302d2e3537322d322e32303820342e323520342e32352030203020302d312e3632352d312e3539354c34312e3435362032342e353961342e33383220342e3338322030203020302d342e33393420306c2d31342e38363420382e36353561342e323520342e32352030203020302d312e36323520312e35393520342e32373320342e3237332030203020302d2e35373220322e3230387631372e34343161342e323720342e3237203020302030202e35373220322e32303820342e323520342e323520302030203020312e36323520312e3539356c31342e38363420382e36353561342e33383220342e33383220302030203020342e33393420306c31302e3038312d352e39303120362e38352d342e3036352031302e3038312d352e39303161342e33383220342e33383220302030203120342e33393420306c372e38383420342e353961342e353220342e353220302030203120312e35383920312e36313620342e353420342e3534203020302031202e36303820322e31383776392e33313161342e323720342e32372030203020312d2e35373220322e32303820342e323520342e32352030203020312d312e36323520312e3539356c2d372e38383420342e37323161342e33383220342e3338322030203020312d342e33393420306c2d372e3838342d342e353961342e353220342e35322030203020312d312e3538392d312e36313620342e353320342e35332030203020312d2e3630382d322e313837762d362e3033326c2d362e383520342e30363576362e30333261342e323720342e3237203020302030202e35373220322e32303820342e323520342e323520302030203020312e36323520312e3539356c31342e38363420382e36353561342e33383220342e33383220302030203020342e33393420306c31342e3836342d382e36353561342e35343520342e35343520302030203020322e3139382d332e3830335635352e35333861342e323720342e32372030203020302d2e3537322d322e32303820342e323520342e32352030203020302d312e3632352d312e3539356c2d31342e3939332d382e3738367a222066696c6c3d2223666666222f3e3c646566733e3c6c696e6561724772616469656e742069643d2261222078313d2230222079313d2230222078323d22323730222079323d2232373022206772616469656e74556e6974733d227573657253706163654f6e557365223e3c73746f702073746f702d636f6c6f723d2276696f6c6574222f3e3c73746f70206f66667365743d2231222073746f702d6f7061636974793d222e3939222f3e3c2f6c696e6561724772616469656e743e3c2f646566733e3c7465787420783d223530252220793d223233312220746578742d616e63686f723d226d6964646c652220666f6e742d73697a653d223237222066696c6c3d2223666666222066696c7465723d2275726c282362292220666f6e742d66616d696c793d22506c7573204a616b617274612053616e732c44656a6156752053616e732c4e6f746f20436f6c6f7220456d6f6a692c4170706c6520436f6c6f7220456d6f6a692c73616e732d73657269662220666f6e742d7765696768743d22626f6c64223e", 540 | "deployedBytecode": "0x6080604052600436106101665760003560e01c8063541e771d116100d1578063b88d4fde1161008a578063c87b56dd11610064578063c87b56dd14610586578063e985e9c5146105c3578063f2c298be14610600578063fb825e5f1461061c57610166565b8063b88d4fde146104f7578063bf40fac114610520578063c1880a981461055d57610166565b8063541e771d146103c15780636352211e146103fe57806370a082311461043b5780638da5cb5b1461047857806395d89b41146104a3578063a22cb465146104ce57610166565b80632644923511610123578063264492351461029f5780632d551432146102dc5780633ccfd60b1461030757806342842e0e1461031e5780634622ab0314610347578063524f38891461038457610166565b806301ffc9a71461016b57806306fdde03146101a8578063081812fc146101d3578063095ea7b31461021057806311dd88451461023957806323b872dd14610276575b600080fd5b34801561017757600080fd5b50610192600480360381019061018d9190613006565b610647565b60405161019f919061304e565b60405180910390f35b3480156101b457600080fd5b506101bd610729565b6040516101ca9190613102565b60405180910390f35b3480156101df57600080fd5b506101fa60048036038101906101f5919061315a565b6107bb565b60405161020791906131c8565b60405180910390f35b34801561021c57600080fd5b506102376004803603810190610232919061320f565b610840565b005b34801561024557600080fd5b50610260600480360381019061025b91906132b4565b610958565b60405161026d9190613102565b60405180910390f35b34801561028257600080fd5b5061029d60048036038101906102989190613301565b610a0b565b005b3480156102ab57600080fd5b506102c660048036038101906102c19190613484565b610a6b565b6040516102d391906131c8565b60405180910390f35b3480156102e857600080fd5b506102f1610ab4565b6040516102fe9190613102565b60405180910390f35b34801561031357600080fd5b5061031c610b42565b005b34801561032a57600080fd5b5061034560048036038101906103409190613301565b610c51565b005b34801561035357600080fd5b5061036e6004803603810190610369919061315a565b610c71565b60405161037b9190613102565b60405180910390f35b34801561039057600080fd5b506103ab60048036038101906103a691906132b4565b610d11565b6040516103b891906134dc565b60405180910390f35b3480156103cd57600080fd5b506103e860048036038101906103e39190613484565b610db7565b6040516103f59190613102565b60405180910390f35b34801561040a57600080fd5b506104256004803603810190610420919061315a565b610e6d565b60405161043291906131c8565b60405180910390f35b34801561044757600080fd5b50610462600480360381019061045d91906134f7565b610f1f565b60405161046f91906134dc565b60405180910390f35b34801561048457600080fd5b5061048d610fd7565b60405161049a91906131c8565b60405180910390f35b3480156104af57600080fd5b506104b8610ffd565b6040516104c59190613102565b60405180910390f35b3480156104da57600080fd5b506104f560048036038101906104f09190613550565b61108f565b005b34801561050357600080fd5b5061051e60048036038101906105199190613631565b6110a5565b005b34801561052c57600080fd5b50610547600480360381019061054291906132b4565b611107565b60405161055491906131c8565b60405180910390f35b34801561056957600080fd5b50610584600480360381019061057f91906136b4565b611152565b005b34801561059257600080fd5b506105ad60048036038101906105a8919061315a565b611236565b6040516105ba9190613102565b60405180910390f35b3480156105cf57600080fd5b506105ea60048036038101906105e59190613735565b611388565b6040516105f7919061304e565b60405180910390f35b61061a600480360381019061061591906132b4565b61141c565b005b34801561062857600080fd5b50610631611943565b60405161063e9190613881565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061071257507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610722575061072182611bbd565b5b9050919050565b606060008054610738906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610764906138d2565b80156107b15780601f10610786576101008083540402835291602001916107b1565b820191906000526020600020905b81548152906001019060200180831161079457829003601f168201915b5050505050905090565b60006107c682611c27565b610805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107fc90613976565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061084b82610e6d565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156108bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b390613a08565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166108db611c93565b73ffffffffffffffffffffffffffffffffffffffff16148061090a575061090981610904611c93565b611388565b5b610949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094090613a9a565b60405180910390fd5b6109538383611c9b565b505050565b6060600e838360405161096c929190613aea565b90815260200160405180910390208054610985906138d2565b80601f01602080910402602001604051908101604052809291908181526020018280546109b1906138d2565b80156109fe5780601f106109d3576101008083540402835291602001916109fe565b820191906000526020600020905b8154815290600101906020018083116109e157829003601f168201915b5050505050905092915050565b610a1c610a16611c93565b82611d54565b610a5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5290613b75565b60405180910390fd5b610a66838383611e32565b505050565b600c818051602081018201805184825260208301602085012081835280955050505050506000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60098054610ac1906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610aed906138d2565b8015610b3a5780601f10610b0f57610100808354040283529160200191610b3a565b820191906000526020600020905b815481529060010190602001808311610b1d57829003601f168201915b505050505081565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b9c57600080fd5b600047905060003373ffffffffffffffffffffffffffffffffffffffff1682604051610bc790613bc6565b60006040518083038185875af1925050503d8060008114610c04576040519150601f19603f3d011682016040523d82523d6000602084013e610c09565b606091505b5050905080610c4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4490613c27565b60405180910390fd5b5050565b610c6c838383604051806020016040528060008152506110a5565b505050565b600d6020528060005260406000206000915090508054610c90906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610cbc906138d2565b8015610d095780601f10610cde57610100808354040283529160200191610d09565b820191906000526020600020905b815481529060010190602001808311610cec57829003601f168201915b505050505081565b600080610d6184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b905060008111610d7057600080fd5b6003811415610d8a576706f05b59d3b20000915050610db1565b6004811415610da457670429d069189e0000915050610db1565b67016345785d8a00009150505b92915050565b600e818051602081018201805184825260208301602085012081835280955050505050506000915090508054610dec906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e18906138d2565b8015610e655780601f10610e3a57610100808354040283529160200191610e65565b820191906000526020600020905b815481529060010190602001808311610e4857829003601f168201915b505050505081565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610f16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0d90613cb9565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8790613d4b565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461100c906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611038906138d2565b80156110855780601f1061105a57610100808354040283529160200191611085565b820191906000526020600020905b81548152906001019060200180831161106857829003601f168201915b5050505050905090565b6110a161109a611c93565b838361224e565b5050565b6110b66110b0611c93565b83611d54565b6110f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ec90613b75565b60405180910390fd5b611101848484846123bb565b50505050565b6000600c838360405161111b929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905092915050565b3373ffffffffffffffffffffffffffffffffffffffff16600c858560405161117b929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111f790613ddd565b60405180910390fd5b8181600e8686604051611214929190613aea565b9081526020016040518091039020919061122f929190612e71565b5050505050565b606061124182611c27565b611280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127790613e6f565b60405180910390fd5b60006006600084815260200190815260200160002080546112a0906138d2565b80601f01602080910402602001604051908101604052809291908181526020018280546112cc906138d2565b80156113195780601f106112ee57610100808354040283529160200191611319565b820191906000526020600020905b8154815290600101906020018083116112fc57829003601f168201915b50505050509050600061132a612417565b9050600081511415611340578192505050611383565b60008251111561137557808260405160200161135d929190613ec0565b60405160208183030381529060405292505050611383565b61137e8461242e565b925050505b919050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8181600361146d83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b101580156114c85750600a6114c583838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b11155b611507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114fe90613f56565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600c8585604051611531929190613aea565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ad90613fc2565b60405180910390fd5b60006115c28585610d11565b905080341015611607576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115fe9061402e565b60405180910390fd5b60008585600960405160200161161f9392919061412e565b60405160208183030381529060405290506000600a82600b6040516020016116499392919061415f565b6040516020818303038152906040529050600061166660076124d5565b905060006116b789898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612099565b905060006116c4826124e3565b90506117b8604051806060016040528060318152602001614c96603191398b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060098054611734906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611760906138d2565b80156117ad5780601f10611782576101008083540402835291602001916117ad565b820191906000526020600020905b81548152906001019060200180831161179057829003601f168201915b505050505086612644565b60006117ee866117c7876126e6565b846040516020016117da9392919061430c565b6040516020818303038152906040526126e6565b905060008160405160200161180391906143b5565b6040516020818303038152906040529050611835604051806060016040528060398152602001614c5d6039913961287e565b6118746040518060400160405280600e81526020017f46696e616c20746f6b656e55524900000000000000000000000000000000000081525082611b21565b611895604051806060016040528060398152602001614cc76039913961287e565b61189f3386612917565b6118a98582612935565b33600c8d8d6040516118bc929190613aea565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b8b600d6000888152602001908152602001600020919061192a929190612e71565b5061193560076129a9565b505050505050505050505050565b60606119836040518060400160405280601f81526020017f47657474696e6720616c6c206e616d65732066726f6d20636f6e74726163740081525061287e565b600061198f60076124d5565b67ffffffffffffffff8111156119a8576119a7613359565b5b6040519080825280602002602001820160405280156119db57816020015b60608152602001906001900390816119c65790505b50905060005b6119eb60076124d5565b811015611b1957600d60008281526020019081526020016000208054611a10906138d2565b80601f0160208091040260200160405190810160405280929190818152602001828054611a3c906138d2565b8015611a895780601f10611a5e57610100808354040283529160200191611a89565b820191906000526020600020905b815481529060010190602001808311611a6c57829003601f168201915b5050505050828281518110611aa157611aa06143d7565b5b6020026020010181905250611b066040518060400160405280601781526020017f4e616d6520666f7220746f6b656e20256420697320257300000000000000000081525082848481518110611af957611af86143d7565b5b60200260200101516129bf565b8080611b1190614435565b9150506119e1565b508091505090565b611bb98282604051602401611b3792919061447e565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611d0e83610e6d565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611d5f82611c27565b611d9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9590614527565b60405180910390fd5b6000611da983610e6d565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611e1857508373ffffffffffffffffffffffffffffffffffffffff16611e00846107bb565b73ffffffffffffffffffffffffffffffffffffffff16145b80611e295750611e288185611388565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611e5282610e6d565b73ffffffffffffffffffffffffffffffffffffffff1614611ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9f906145b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611f18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0f9061464b565b60405180910390fd5b611f23838383612a87565b611f2e600082611c9b565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611f7e919061466b565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611fd5919061469f565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612094838383612a8c565b505050565b60008060008084519050600092505b808210156122435760008583815181106120c5576120c46143d7565b5b602001015160f81c60f81b9050608060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121145760018361210d919061469f565b925061222f565b60e060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121565760028361214f919061469f565b925061222e565b60f060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916101561219857600383612191919061469f565b925061222d565b60f8801b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191610156121d9576004836121d2919061469f565b925061222c565b60fc60f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916101561221b57600583612214919061469f565b925061222b565b600683612228919061469f565b92505b5b5b5b5b50828061223b90614435565b9350506120a8565b829350505050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156122bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b490614741565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516123ae919061304e565b60405180910390a3505050565b6123c6848484611e32565b6123d284848484612a91565b612411576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612408906147d3565b60405180910390fd5b50505050565b606060405180602001604052806000815250905090565b606061243982611c27565b612478576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246f90614865565b60405180910390fd5b6000612482612417565b905060008151116124a257604051806020016040528060008152506124cd565b806124ac846124e3565b6040516020016124bd929190613ec0565b6040516020818303038152906040525b915050919050565b600081600001549050919050565b6060600082141561252b576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061263f565b600082905060005b6000821461255d57808061254690614435565b915050600a8261255691906148b4565b9150612533565b60008167ffffffffffffffff81111561257957612578613359565b5b6040519080825280601f01601f1916602001820160405280156125ab5781602001600182028036833780820191505090505b5090505b60008514612638576001826125c4919061466b565b9150600a856125d391906148e5565b60306125df919061469f565b60f81b8183815181106125f5576125f46143d7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561263191906148b4565b94506125af565b8093505050505b919050565b6126e08484848460405160240161265e9493929190614916565b6040516020818303038152906040527f9fd009f5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b50505050565b6060600082519050600081141561270f5760405180602001604052806000815250915050612879565b60006003600283612720919061469f565b61272a91906148b4565b60046127369190614970565b90506000602082612747919061469f565b67ffffffffffffffff8111156127605761275f613359565b5b6040519080825280601f01601f1916602001820160405280156127925781602001600182028036833780820191505090505b5090506000604051806060016040528060408152602001614d00604091399050600181016020830160005b868110156128365760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506127bd565b50600386066001811461285057600281146128605761286b565b613d3d60f01b600283035261286b565b603d60f81b60018303525b508484525050819450505050505b919050565b612914816040516024016128929190613102565b6040516020818303038152906040527f41304fac000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b50565b612931828260405180602001604052806000815250612c19565b5050565b61293e82611c27565b61297d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297490614a3c565b60405180910390fd5b806006600084815260200190815260200160002090805190602001906129a4929190612ef7565b505050565b6001816000016000828254019250508190555050565b612a598383836040516024016129d793929190614a5c565b6040516020818303038152906040527fa3f5c739000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612a5e565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b505050565b505050565b6000612ab28473ffffffffffffffffffffffffffffffffffffffff16612c74565b15612c0c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612adb611c93565b8786866040518563ffffffff1660e01b8152600401612afd9493929190614af6565b6020604051808303816000875af1925050508015612b3957506040513d601f19601f82011682018060405250810190612b369190614b57565b60015b612bbc573d8060008114612b69576040519150601f19603f3d011682016040523d82523d6000602084013e612b6e565b606091505b50600081511415612bb4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bab906147d3565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612c11565b600190505b949350505050565b612c238383612c97565b612c306000848484612a91565b612c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c66906147d3565b60405180910390fd5b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612d07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cfe90614bd0565b60405180910390fd5b612d1081611c27565b15612d50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4790614c3c565b60405180910390fd5b612d5c60008383612a87565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612dac919061469f565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612e6d60008383612a8c565b5050565b828054612e7d906138d2565b90600052602060002090601f016020900481019282612e9f5760008555612ee6565b82601f10612eb857803560ff1916838001178555612ee6565b82800160010185558215612ee6579182015b82811115612ee5578235825591602001919060010190612eca565b5b509050612ef39190612f7d565b5090565b828054612f03906138d2565b90600052602060002090601f016020900481019282612f255760008555612f6c565b82601f10612f3e57805160ff1916838001178555612f6c565b82800160010185558215612f6c579182015b82811115612f6b578251825591602001919060010190612f50565b5b509050612f799190612f7d565b5090565b5b80821115612f96576000816000905550600101612f7e565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fe381612fae565b8114612fee57600080fd5b50565b60008135905061300081612fda565b92915050565b60006020828403121561301c5761301b612fa4565b5b600061302a84828501612ff1565b91505092915050565b60008115159050919050565b61304881613033565b82525050565b6000602082019050613063600083018461303f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156130a3578082015181840152602081019050613088565b838111156130b2576000848401525b50505050565b6000601f19601f8301169050919050565b60006130d482613069565b6130de8185613074565b93506130ee818560208601613085565b6130f7816130b8565b840191505092915050565b6000602082019050818103600083015261311c81846130c9565b905092915050565b6000819050919050565b61313781613124565b811461314257600080fd5b50565b6000813590506131548161312e565b92915050565b6000602082840312156131705761316f612fa4565b5b600061317e84828501613145565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006131b282613187565b9050919050565b6131c2816131a7565b82525050565b60006020820190506131dd60008301846131b9565b92915050565b6131ec816131a7565b81146131f757600080fd5b50565b600081359050613209816131e3565b92915050565b6000806040838503121561322657613225612fa4565b5b6000613234858286016131fa565b925050602061324585828601613145565b9150509250929050565b600080fd5b600080fd5b600080fd5b60008083601f8401126132745761327361324f565b5b8235905067ffffffffffffffff81111561329157613290613254565b5b6020830191508360018202830111156132ad576132ac613259565b5b9250929050565b600080602083850312156132cb576132ca612fa4565b5b600083013567ffffffffffffffff8111156132e9576132e8612fa9565b5b6132f58582860161325e565b92509250509250929050565b60008060006060848603121561331a57613319612fa4565b5b6000613328868287016131fa565b9350506020613339868287016131fa565b925050604061334a86828701613145565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613391826130b8565b810181811067ffffffffffffffff821117156133b0576133af613359565b5b80604052505050565b60006133c3612f9a565b90506133cf8282613388565b919050565b600067ffffffffffffffff8211156133ef576133ee613359565b5b6133f8826130b8565b9050602081019050919050565b82818337600083830152505050565b6000613427613422846133d4565b6133b9565b90508281526020810184848401111561344357613442613354565b5b61344e848285613405565b509392505050565b600082601f83011261346b5761346a61324f565b5b813561347b848260208601613414565b91505092915050565b60006020828403121561349a57613499612fa4565b5b600082013567ffffffffffffffff8111156134b8576134b7612fa9565b5b6134c484828501613456565b91505092915050565b6134d681613124565b82525050565b60006020820190506134f160008301846134cd565b92915050565b60006020828403121561350d5761350c612fa4565b5b600061351b848285016131fa565b91505092915050565b61352d81613033565b811461353857600080fd5b50565b60008135905061354a81613524565b92915050565b6000806040838503121561356757613566612fa4565b5b6000613575858286016131fa565b92505060206135868582860161353b565b9150509250929050565b600067ffffffffffffffff8211156135ab576135aa613359565b5b6135b4826130b8565b9050602081019050919050565b60006135d46135cf84613590565b6133b9565b9050828152602081018484840111156135f0576135ef613354565b5b6135fb848285613405565b509392505050565b600082601f8301126136185761361761324f565b5b81356136288482602086016135c1565b91505092915050565b6000806000806080858703121561364b5761364a612fa4565b5b6000613659878288016131fa565b945050602061366a878288016131fa565b935050604061367b87828801613145565b925050606085013567ffffffffffffffff81111561369c5761369b612fa9565b5b6136a887828801613603565b91505092959194509250565b600080600080604085870312156136ce576136cd612fa4565b5b600085013567ffffffffffffffff8111156136ec576136eb612fa9565b5b6136f88782880161325e565b9450945050602085013567ffffffffffffffff81111561371b5761371a612fa9565b5b6137278782880161325e565b925092505092959194509250565b6000806040838503121561374c5761374b612fa4565b5b600061375a858286016131fa565b925050602061376b858286016131fa565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b60006137bd82613069565b6137c781856137a1565b93506137d7818560208601613085565b6137e0816130b8565b840191505092915050565b60006137f783836137b2565b905092915050565b6000602082019050919050565b600061381782613775565b6138218185613780565b93508360208202850161383385613791565b8060005b8581101561386f578484038952815161385085826137eb565b945061385b836137ff565b925060208a01995050600181019050613837565b50829750879550505050505092915050565b6000602082019050818103600083015261389b818461380c565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806138ea57607f821691505b602082108114156138fe576138fd6138a3565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000613960602c83613074565b915061396b82613904565b604082019050919050565b6000602082019050818103600083015261398f81613953565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006139f2602183613074565b91506139fd82613996565b604082019050919050565b60006020820190508181036000830152613a21816139e5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b6000613a84603883613074565b9150613a8f82613a28565b604082019050919050565b60006020820190508181036000830152613ab381613a77565b9050919050565b600081905092915050565b6000613ad18385613aba565b9350613ade838584613405565b82840190509392505050565b6000613af7828486613ac5565b91508190509392505050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b6000613b5f603183613074565b9150613b6a82613b03565b604082019050919050565b60006020820190508181036000830152613b8e81613b52565b9050919050565b600081905092915050565b50565b6000613bb0600083613b95565b9150613bbb82613ba0565b600082019050919050565b6000613bd182613ba3565b9150819050919050565b7f4661696c656420746f207769746864726177204d617469630000000000000000600082015250565b6000613c11601883613074565b9150613c1c82613bdb565b602082019050919050565b60006020820190508181036000830152613c4081613c04565b9050919050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000613ca3602983613074565b9150613cae82613c47565b604082019050919050565b60006020820190508181036000830152613cd281613c96565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000613d35602a83613074565b9150613d4082613cd9565b604082019050919050565b60006020820190508181036000830152613d6481613d28565b9050919050565b7f4f6e6c7920746865206f776e6572206f662074686520646f6d61696e2063616e60008201527f207365742061207265636f726400000000000000000000000000000000000000602082015250565b6000613dc7602d83613074565b9150613dd282613d6b565b604082019050919050565b60006020820190508181036000830152613df681613dba565b9050919050565b7f45524337323155524953746f726167653a2055524920717565727920666f722060008201527f6e6f6e6578697374656e7420746f6b656e000000000000000000000000000000602082015250565b6000613e59603183613074565b9150613e6482613dfd565b604082019050919050565b60006020820190508181036000830152613e8881613e4c565b9050919050565b6000613e9a82613069565b613ea48185613aba565b9350613eb4818560208601613085565b80840191505092915050565b6000613ecc8285613e8f565b9150613ed88284613e8f565b91508190509392505050565b7f4e616d65732063616e2068617665206265747765656e203320616e642031302060008201527f6368617273000000000000000000000000000000000000000000000000000000602082015250565b6000613f40602583613074565b9150613f4b82613ee4565b604082019050919050565b60006020820190508181036000830152613f6f81613f33565b9050919050565b7f4e616d6520697320616c726561647920696e2075736500000000000000000000600082015250565b6000613fac601683613074565b9150613fb782613f76565b602082019050919050565b60006020820190508181036000830152613fdb81613f9f565b9050919050565b7f4e6f7420656e6f756768204d4154494320706169640000000000000000000000600082015250565b6000614018601583613074565b915061402382613fe2565b602082019050919050565b600060208201905081810360008301526140478161400b565b9050919050565b7f2e00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614084600183613aba565b915061408f8261404e565b600182019050919050565b60008190508160005260206000209050919050565b600081546140bc816138d2565b6140c68186613aba565b945060018216600081146140e157600181146140f257614125565b60ff19831686528186019350614125565b6140fb8561409a565b60005b8381101561411d578154818901526001820191506020810190506140fe565b838801955050505b50505092915050565b600061413b828587613ac5565b915061414682614077565b915061415282846140af565b9150819050949350505050565b600061416b82866140af565b91506141778285613e8f565b915061418382846140af565b9150819050949350505050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000600082015250565b60006141c6600a83613aba565b91506141d182614190565b600a82019050919050565b7f222c20226465736372697074696f6e223a20224120646f6d61696e206f6e207460008201527f6865204e696e6a61206e616d652073657276696365222c2022696d616765223a60208201527f2022646174613a696d6167652f7376672b786d6c3b6261736536342c00000000604082015250565b600061425e605c83613aba565b9150614269826141dc565b605c82019050919050565b7f222c226c656e677468223a220000000000000000000000000000000000000000600082015250565b60006142aa600c83613aba565b91506142b582614274565b600c82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b60006142f6600283613aba565b9150614301826142c0565b600282019050919050565b6000614317826141b9565b91506143238286613e8f565b915061432e82614251565b915061433a8285613e8f565b91506143458261429d565b91506143518284613e8f565b915061435c826142e9565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061439f601d83613aba565b91506143aa82614369565b601d82019050919050565b60006143c082614392565b91506143cc8284613e8f565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061444082613124565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561447357614472614406565b5b600182019050919050565b6000604082019050818103600083015261449881856130c9565b905081810360208301526144ac81846130c9565b90509392505050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000614511602c83613074565b915061451c826144b5565b604082019050919050565b6000602082019050818103600083015261454081614504565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006145a3602583613074565b91506145ae82614547565b604082019050919050565b600060208201905081810360008301526145d281614596565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614635602483613074565b9150614640826145d9565b604082019050919050565b6000602082019050818103600083015261466481614628565b9050919050565b600061467682613124565b915061468183613124565b92508282101561469457614693614406565b5b828203905092915050565b60006146aa82613124565b91506146b583613124565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156146ea576146e9614406565b5b828201905092915050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b600061472b601983613074565b9150614736826146f5565b602082019050919050565b6000602082019050818103600083015261475a8161471e565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b60006147bd603283613074565b91506147c882614761565b604082019050919050565b600060208201905081810360008301526147ec816147b0565b9050919050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b600061484f602f83613074565b915061485a826147f3565b604082019050919050565b6000602082019050818103600083015261487e81614842565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148bf82613124565b91506148ca83613124565b9250826148da576148d9614885565b5b828204905092915050565b60006148f082613124565b91506148fb83613124565b92508261490b5761490a614885565b5b828206905092915050565b6000608082019050818103600083015261493081876130c9565b9050818103602083015261494481866130c9565b9050818103604083015261495881856130c9565b905061496760608301846134cd565b95945050505050565b600061497b82613124565b915061498683613124565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156149bf576149be614406565b5b828202905092915050565b7f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60008201527f6578697374656e7420746f6b656e000000000000000000000000000000000000602082015250565b6000614a26602e83613074565b9150614a31826149ca565b604082019050919050565b60006020820190508181036000830152614a5581614a19565b9050919050565b60006060820190508181036000830152614a7681866130c9565b9050614a8560208301856134cd565b8181036040830152614a9781846130c9565b9050949350505050565b600081519050919050565b600082825260208201905092915050565b6000614ac882614aa1565b614ad28185614aac565b9350614ae2818560208601613085565b614aeb816130b8565b840191505092915050565b6000608082019050614b0b60008301876131b9565b614b1860208301866131b9565b614b2560408301856134cd565b8181036060830152614b378184614abd565b905095945050505050565b600081519050614b5181612fda565b92915050565b600060208284031215614b6d57614b6c612fa4565b5b6000614b7b84828501614b42565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000614bba602083613074565b9150614bc582614b84565b602082019050919050565b60006020820190508181036000830152614be981614bad565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000614c26601c83613074565b9150614c3182614bf0565b602082019050919050565b60006020820190508181036000830152614c5581614c19565b905091905056fe0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d5265676973746572696e672025732e2573206f6e2074686520636f6e7472616374207769746820746f6b656e49442025642d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0a4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220f34ae7380f9822c278ead0324dee89e34ba7d535e8d05183ad425e34b68f48ba64736f6c634300080a0033", 541 | "linkReferences": {}, 542 | "deployedLinkReferences": {} 543 | } 544 | --------------------------------------------------------------------------------