diff --git a/packages/hyperverse-polygon-randompick/.gitignore b/packages/hyperverse-polygon-randompick/.gitignore new file mode 100644 index 00000000..48e34b86 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/.gitignore @@ -0,0 +1,10 @@ +node_modules +.env +coverage +coverage.json +typechain + +#Hardhat files +cache +artifacts +distribution diff --git a/packages/hyperverse-polygon-randompick/CHANGELOG.md b/packages/hyperverse-polygon-randompick/CHANGELOG.md new file mode 100644 index 00000000..650ce148 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/CHANGELOG.md @@ -0,0 +1,5 @@ +# @decentology/hyperverse-polygon-randompick + +## 1.0.0 + +- initializing package \ No newline at end of file diff --git a/packages/hyperverse-polygon-randompick/contracts/RandomPick.sol b/packages/hyperverse-polygon-randompick/contracts/RandomPick.sol new file mode 100644 index 00000000..2573e0d6 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/contracts/RandomPick.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol"; + +/** + * Request testnet LINK and ETH here: https://faucets.chain.link/ + * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/ + */ +contract RandomPick is VRFConsumerBase { + bytes32 internal keyHash; + uint256 internal fee; + // Where you can access your results + // requestId => result + mapping(bytes32 => int256) public results; + /* Helpers along the way */ + // requestId => input + mapping(bytes32 => int256[]) public randomList; + // requestId => tenant address + mapping(bytes32 => address) public requestIdToAddress; + event StartedRandomPick(address tenant, bytes32 requestId); + + /** + * Constructor inherits VRFConsumerBase + * All of this info is gotten from: https://docs.chain.link/docs/vrf-contracts/ + * + * Network: Rinkeby + * Chainlink VRF Coordinator address: 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B + * LINK token address: 0x01BE23585060835E02B77ef475b0Cc51aA1e0709 + * Key Hash: 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311 + * Fee: 0.1 LINK + */ + constructor() + VRFConsumerBase( + 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B, // VRF Coordinator + 0x01BE23585060835E02B77ef475b0Cc51aA1e0709 // LINK Token on Rinkeby + ) + { + keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311; + fee = 0.1 * 10**18; // 0.1 LINK (Varies by network) + } + + /** + * Requests randomness + * Everything set in here is done on the first transaction + */ + function startRandomPick(int256[] memory numbers) public returns (bytes32) { + require( + LINK.balanceOf(address(this)) >= fee, + "Not enough LINK - fill contract with faucet" + ); + bytes32 requestId = requestRandomness(keyHash, fee); + randomList[requestId] = numbers; + requestIdToAddress[requestId] = msg.sender; + emit StartedRandomPick(msg.sender, requestId); + return requestId; + } + + /** + * Callback function used by VRF Coordinator + * Everything set in here is done on the second transaction + */ + function fulfillRandomness(bytes32 requestId, uint256 randomness) + internal + override + { + uint256 length = randomList[requestId].length; + uint256 index = randomness % length; + results[requestId] = randomList[requestId][index]; + } +} diff --git a/packages/hyperverse-polygon-randompick/hardhat.config.js b/packages/hyperverse-polygon-randompick/hardhat.config.js new file mode 100644 index 00000000..cfeed558 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/hardhat.config.js @@ -0,0 +1,21 @@ +require("@nomiclabs/hardhat-waffle"); + +// This is a sample Hardhat task. To learn how to create your own go to +// https://hardhat.org/guides/create-task.html +task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { + const accounts = await hre.ethers.getSigners(); + + for (const account of accounts) { + console.log(account.address); + } +}); + +// You need to export an object to set up your config +// Go to https://hardhat.org/config/ to learn more + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +module.exports = { + solidity: "0.8.4", +}; diff --git a/packages/hyperverse-polygon-randompick/index.ts b/packages/hyperverse-polygon-randompick/index.ts new file mode 100644 index 00000000..a461c3b0 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/index.ts @@ -0,0 +1 @@ +export * from "./source"; diff --git a/packages/hyperverse-polygon-randompick/package.json b/packages/hyperverse-polygon-randompick/package.json new file mode 100644 index 00000000..d0cc273c --- /dev/null +++ b/packages/hyperverse-polygon-randompick/package.json @@ -0,0 +1,44 @@ +{ + "name": "@decentology/hyperverse-polygon-randompick", + "version": "1.0.0", + "source": "./source/index.ts", + "types": "./distribution/index.d.ts", + "main": "./distribution/index.js", + "license": "MIT", + "scripts": { + "test": "hardhat test", + "build": "parcel build", + "clean": "rimraf ./distribution" + }, + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "react": "^17.0.2" + }, + "files": [ + "distribution", + "utils" + ], + "dependencies": { + "@chainlink/contracts": "^0.4.0", + "@decentology/hyperverse": "^1.0.9", + "@decentology/hyperverse-polygon": "^1.0.0", + "@decentology/hyperverse-storage-skynet": "^1.0.8", + "@decentology/unstated-next": "^1.1.1", + "ethers": "^5.5.3", + "react-query": "^3.34.7", + "react-use": "^17.3.2", + "skynet-js": "^4.0.23-beta" + }, + "devDependencies": { + "@decentology/config": "^1.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.4", + "@nomiclabs/hardhat-waffle": "^2.0.2", + "chai": "^4.3.4", + "ethereum-waffle": "^3.4.0", + "hardhat": "^2.8.3", + "parcel": "^2.2.1", + "rimraf": "^3.0.2" + } +} diff --git a/packages/hyperverse-polygon-randompick/source/Provider.tsx b/packages/hyperverse-polygon-randompick/source/Provider.tsx new file mode 100644 index 00000000..28bacc04 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/source/Provider.tsx @@ -0,0 +1,22 @@ +import { FC } from "react"; +import { QueryClientProvider, QueryClient } from "react-query"; +import ABI from "../utils/RandomPick.json"; +import { HyperverseModuleInstance } from "@decentology/hyperverse"; +import { RandomPick } from "./useRandomPick"; +const client = new QueryClient(); + +export const ContractABI = ABI.abi; +export const CONTRACT_ADDRESS = "0x9FC0FE344758ff0dB70Aa7c864b2de53A79CA776"; +export const TENANT_ADDRESS = "0x45e4c90801b1a17c178bB9855aA181A886DAA603"; + +const Provider: FC = ({ children, tenantId }:{children: any, tenantId: string}) => { + return ( + + + {children} + + + ); +}; + +export { Provider }; diff --git a/packages/hyperverse-polygon-randompick/source/index.ts b/packages/hyperverse-polygon-randompick/source/index.ts new file mode 100644 index 00000000..cbad2294 --- /dev/null +++ b/packages/hyperverse-polygon-randompick/source/index.ts @@ -0,0 +1,2 @@ +export { useRandomPick } from './useRandomPick' +export { Provider } from "./Provider"; diff --git a/packages/hyperverse-polygon-randompick/source/useRandomPick.ts b/packages/hyperverse-polygon-randompick/source/useRandomPick.ts new file mode 100644 index 00000000..6945d98c --- /dev/null +++ b/packages/hyperverse-polygon-randompick/source/useRandomPick.ts @@ -0,0 +1,104 @@ +import { useState, useEffect, useCallback } from "react"; +import { useMutation, UseMutationOptions, useQuery } from "react-query"; +import { BigNumber, ethers } from "ethers"; +import { usePolygon } from "@decentology/hyperverse-polygon"; +import { ContractABI, CONTRACT_ADDRESS } from "./Provider"; +import { createContainer, useContainer } from "@decentology/unstated-next"; + +type ContractState = ethers.Contract; +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); +function RandomPickState( + initialState: { tenantId: string } = { tenantId: "" } +) { + const { tenantId } = initialState; + const { address, web3Provider, provider, connect } = usePolygon(); + const [contract, setRandomPickContract] = useState( + new ethers.Contract( + CONTRACT_ADDRESS, + ContractABI, + provider + ) as ContractState + ); + + const setup = useCallback(async () => { + const signer = await web3Provider?.getSigner(); + if (signer && contract) { + const ctr = contract.connect(signer) as ContractState; + setRandomPickContract(ctr); + } + }, [web3Provider]); + + const errors = (err: any) => { + throw err; + // throw new Error("Something went wrong!"); + }; + + useEffect(() => { + if (web3Provider) { + setup(); + } + }, [web3Provider]); + + const startRandomPick = useCallback( + async (numbers: Number[]) => { + try { + const tx = await contract.startRandomPick(numbers); + console.log("Sending..."); + const waited = await tx.wait(); + const event = waited.events.filter( + (x: any) => x.event == "StartedRandomPick" + )[0]; + const requestId = event.args[1]; + console.log("RequestId:", requestId); + return requestId; + } catch (err) { + errors(err); + throw err; + } + }, + [contract] + ); + + const getRandomPick = useCallback( + async (requestId: string) => { + return new Promise(async (resolve, reject) => { + try { + if (!requestId) { + return null; + } + let randomPick = (await contract.results(requestId)) as BigNumber; + while (randomPick.toNumber() === 0) { + await sleep(1000); + randomPick = (await contract.results(requestId)) as BigNumber; + } + + return resolve(randomPick.toNumber()); + } catch (err) { + return reject(err); + } + }); + }, + [contract] + ); + + return { + tenantId, + contract, + StartRandomPick: ( + options?: Omit< + UseMutationOptions, + "mutationFn" + > + ) => useMutation((numbers: Number[]) => startRandomPick(numbers)), + GetRandomPick: (requestId: string) => + useQuery(["getRandomPick"], () => getRandomPick(requestId), { + enabled: !!requestId, + }), + }; +} + +export const RandomPick = createContainer(RandomPickState); + +export function useRandomPick() { + return useContainer(RandomPick); +} diff --git a/packages/hyperverse-polygon-randompick/test/randompick-test.js b/packages/hyperverse-polygon-randompick/test/randompick-test.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/hyperverse-polygon-randompick/tsconfig.json b/packages/hyperverse-polygon-randompick/tsconfig.json new file mode 100644 index 00000000..c8791f5f --- /dev/null +++ b/packages/hyperverse-polygon-randompick/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@decentology/config/react-library.json", + "include": ["source/**/*.ts", "source/**/*.tsx", "**/*.json"], + "exclude": ["distribution", "node_modules"], + "compilerOptions": { + "resolveJsonModule": true + } +} diff --git a/packages/hyperverse-polygon-randompick/utils/RandomPick.json b/packages/hyperverse-polygon-randompick/utils/RandomPick.json new file mode 100644 index 00000000..13bfc7dd --- /dev/null +++ b/packages/hyperverse-polygon-randompick/utils/RandomPick.json @@ -0,0 +1,134 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RandomPick", + "sourceName": "contracts/RandomPick.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tenant", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "StartedRandomPick", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "randomList", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "name": "rawFulfillRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "requestIdToAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "results", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256[]", + "name": "numbers", + "type": "int256[]" + } + ], + "name": "startRandomPick", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60c060405234801561001057600080fd5b5073b3dccb4cf7a26f6cf6b120cf5a73875b7bbc655b7301be23585060835e02b77ef475b0cc51aa1e07098173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505050507f2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c131160001b60018190555067016345785d8a000060028190555060805160601c60a05160601c610ed661011d60003960008181610340015261044d01526000818161015701526104110152610ed66000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634c6b25b11461005c578063816dd4901461008c57806394917f4c146100bc57806394985ddd146100ec578063bc64beee14610108575b600080fd5b6100766004803603810190610071919061084c565b610138565b6040516100839190610afa565b60405180910390f35b6100a660048036038101906100a191906107e2565b610150565b6040516100b39190610a71565b60405180910390f35b6100d660048036038101906100d19190610875565b61030d565b6040516100e39190610afa565b60405180910390f35b61010660048036038101906101019190610875565b61033e565b005b610122600480360381019061011d919061084c565b6103da565b60405161012f91906109ef565b60405180910390f35b60036020528060005260406000206000915090505481565b60006002547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016101ae91906109ef565b60206040518083038186803b1580156101c657600080fd5b505afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906108b1565b101561023f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023690610b15565b60405180910390fd5b600061024f60015460025461040d565b905082600460008381526020019081526020016000209080519060200190610278929190610679565b50336005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f3d95cbc75e00c352f4ac7c91bc32f77836c6eff14f4cbef2a3eb8905a4eca7b433826040516102fc929190610a0a565b60405180910390a180915050919050565b6004602052816000526040600020818154811061032957600080fd5b90600052602060002001600091509150505481565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c390610b35565b60405180910390fd5b6103d6828261056c565b5050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea07f000000000000000000000000000000000000000000000000000000000000000084866000604051602001610481929190610a8c565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016104ae93929190610a33565b602060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105009190610823565b506000610522846000306000808981526020019081526020016000205461060a565b90506001600080868152602001908152602001600020546105439190610bd3565b600080868152602001908152602001600020819055506105638482610646565b91505092915050565b600060046000848152602001908152602001600020805490509050600081836105959190610cfd565b90506004600085815260200190815260200160002081815481106105e2577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600360008681526020019081526020016000208190555050505050565b6000848484846040516020016106239493929190610ab5565b6040516020818303038152906040528051906020012060001c9050949350505050565b6000828260405160200161065b9291906109c3565b60405160208183030381529060405280519060200120905092915050565b8280548282559060005260206000209081019282156106b5579160200282015b828111156106b4578251825591602001919060010190610699565b5b5090506106c291906106c6565b5090565b5b808211156106df5760008160009055506001016106c7565b5090565b60006106f66106f184610b7a565b610b55565b9050808382526020820190508285602086028201111561071557600080fd5b60005b85811015610745578161072b88826107a3565b845260208401935060208301925050600181019050610718565b5050509392505050565b600082601f83011261076057600080fd5b81356107708482602086016106e3565b91505092915050565b60008151905061078881610e44565b92915050565b60008135905061079d81610e5b565b92915050565b6000813590506107b281610e72565b92915050565b6000813590506107c781610e89565b92915050565b6000815190506107dc81610e89565b92915050565b6000602082840312156107f457600080fd5b600082013567ffffffffffffffff81111561080e57600080fd5b61081a8482850161074f565b91505092915050565b60006020828403121561083557600080fd5b600061084384828501610779565b91505092915050565b60006020828403121561085e57600080fd5b600061086c8482850161078e565b91505092915050565b6000806040838503121561088857600080fd5b60006108968582860161078e565b92505060206108a7858286016107b8565b9150509250929050565b6000602082840312156108c357600080fd5b60006108d1848285016107cd565b91505092915050565b6108e381610c29565b82525050565b6108f281610c47565b82525050565b61090961090482610c47565b610ce9565b82525050565b600061091a82610ba6565b6109248185610bb1565b9350610934818560208601610c85565b61093d81610dbb565b840191505092915050565b61095181610c51565b82525050565b6000610964602b83610bc2565b915061096f82610dcc565b604082019050919050565b6000610987601f83610bc2565b915061099282610e1b565b602082019050919050565b6109a681610c7b565b82525050565b6109bd6109b882610c7b565b610cf3565b82525050565b60006109cf82856108f8565b6020820191506109df82846109ac565b6020820191508190509392505050565b6000602082019050610a0460008301846108da565b92915050565b6000604082019050610a1f60008301856108da565b610a2c60208301846108e9565b9392505050565b6000606082019050610a4860008301866108da565b610a55602083018561099d565b8181036040830152610a67818461090f565b9050949350505050565b6000602082019050610a8660008301846108e9565b92915050565b6000604082019050610aa160008301856108e9565b610aae602083018461099d565b9392505050565b6000608082019050610aca60008301876108e9565b610ad7602083018661099d565b610ae460408301856108da565b610af1606083018461099d565b95945050505050565b6000602082019050610b0f6000830184610948565b92915050565b60006020820190508181036000830152610b2e81610957565b9050919050565b60006020820190508181036000830152610b4e8161097a565b9050919050565b6000610b5f610b70565b9050610b6b8282610cb8565b919050565b6000604051905090565b600067ffffffffffffffff821115610b9557610b94610d8c565b5b602082029050602081019050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610bde82610c7b565b9150610be983610c7b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610c1e57610c1d610d2e565b5b828201905092915050565b6000610c3482610c5b565b9050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610ca3578082015181840152602081019050610c88565b83811115610cb2576000848401525b50505050565b610cc182610dbb565b810181811067ffffffffffffffff82111715610ce057610cdf610d8c565b5b80604052505050565b6000819050919050565b6000819050919050565b6000610d0882610c7b565b9150610d1383610c7b565b925082610d2357610d22610d5d565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e74726163742060008201527f7769746820666175636574000000000000000000000000000000000000000000602082015250565b7f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00600082015250565b610e4d81610c3b565b8114610e5857600080fd5b50565b610e6481610c47565b8114610e6f57600080fd5b50565b610e7b81610c51565b8114610e8657600080fd5b50565b610e9281610c7b565b8114610e9d57600080fd5b5056fea26469706673582212207e5894b476f0d46facfa4872791b634b2f715098ab3466adc631fc6f825421cb64736f6c63430008040033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80634c6b25b11461005c578063816dd4901461008c57806394917f4c146100bc57806394985ddd146100ec578063bc64beee14610108575b600080fd5b6100766004803603810190610071919061084c565b610138565b6040516100839190610afa565b60405180910390f35b6100a660048036038101906100a191906107e2565b610150565b6040516100b39190610a71565b60405180910390f35b6100d660048036038101906100d19190610875565b61030d565b6040516100e39190610afa565b60405180910390f35b61010660048036038101906101019190610875565b61033e565b005b610122600480360381019061011d919061084c565b6103da565b60405161012f91906109ef565b60405180910390f35b60036020528060005260406000206000915090505481565b60006002547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016101ae91906109ef565b60206040518083038186803b1580156101c657600080fd5b505afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906108b1565b101561023f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023690610b15565b60405180910390fd5b600061024f60015460025461040d565b905082600460008381526020019081526020016000209080519060200190610278929190610679565b50336005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f3d95cbc75e00c352f4ac7c91bc32f77836c6eff14f4cbef2a3eb8905a4eca7b433826040516102fc929190610a0a565b60405180910390a180915050919050565b6004602052816000526040600020818154811061032957600080fd5b90600052602060002001600091509150505481565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c390610b35565b60405180910390fd5b6103d6828261056c565b5050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea07f000000000000000000000000000000000000000000000000000000000000000084866000604051602001610481929190610a8c565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016104ae93929190610a33565b602060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105009190610823565b506000610522846000306000808981526020019081526020016000205461060a565b90506001600080868152602001908152602001600020546105439190610bd3565b600080868152602001908152602001600020819055506105638482610646565b91505092915050565b600060046000848152602001908152602001600020805490509050600081836105959190610cfd565b90506004600085815260200190815260200160002081815481106105e2577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600360008681526020019081526020016000208190555050505050565b6000848484846040516020016106239493929190610ab5565b6040516020818303038152906040528051906020012060001c9050949350505050565b6000828260405160200161065b9291906109c3565b60405160208183030381529060405280519060200120905092915050565b8280548282559060005260206000209081019282156106b5579160200282015b828111156106b4578251825591602001919060010190610699565b5b5090506106c291906106c6565b5090565b5b808211156106df5760008160009055506001016106c7565b5090565b60006106f66106f184610b7a565b610b55565b9050808382526020820190508285602086028201111561071557600080fd5b60005b85811015610745578161072b88826107a3565b845260208401935060208301925050600181019050610718565b5050509392505050565b600082601f83011261076057600080fd5b81356107708482602086016106e3565b91505092915050565b60008151905061078881610e44565b92915050565b60008135905061079d81610e5b565b92915050565b6000813590506107b281610e72565b92915050565b6000813590506107c781610e89565b92915050565b6000815190506107dc81610e89565b92915050565b6000602082840312156107f457600080fd5b600082013567ffffffffffffffff81111561080e57600080fd5b61081a8482850161074f565b91505092915050565b60006020828403121561083557600080fd5b600061084384828501610779565b91505092915050565b60006020828403121561085e57600080fd5b600061086c8482850161078e565b91505092915050565b6000806040838503121561088857600080fd5b60006108968582860161078e565b92505060206108a7858286016107b8565b9150509250929050565b6000602082840312156108c357600080fd5b60006108d1848285016107cd565b91505092915050565b6108e381610c29565b82525050565b6108f281610c47565b82525050565b61090961090482610c47565b610ce9565b82525050565b600061091a82610ba6565b6109248185610bb1565b9350610934818560208601610c85565b61093d81610dbb565b840191505092915050565b61095181610c51565b82525050565b6000610964602b83610bc2565b915061096f82610dcc565b604082019050919050565b6000610987601f83610bc2565b915061099282610e1b565b602082019050919050565b6109a681610c7b565b82525050565b6109bd6109b882610c7b565b610cf3565b82525050565b60006109cf82856108f8565b6020820191506109df82846109ac565b6020820191508190509392505050565b6000602082019050610a0460008301846108da565b92915050565b6000604082019050610a1f60008301856108da565b610a2c60208301846108e9565b9392505050565b6000606082019050610a4860008301866108da565b610a55602083018561099d565b8181036040830152610a67818461090f565b9050949350505050565b6000602082019050610a8660008301846108e9565b92915050565b6000604082019050610aa160008301856108e9565b610aae602083018461099d565b9392505050565b6000608082019050610aca60008301876108e9565b610ad7602083018661099d565b610ae460408301856108da565b610af1606083018461099d565b95945050505050565b6000602082019050610b0f6000830184610948565b92915050565b60006020820190508181036000830152610b2e81610957565b9050919050565b60006020820190508181036000830152610b4e8161097a565b9050919050565b6000610b5f610b70565b9050610b6b8282610cb8565b919050565b6000604051905090565b600067ffffffffffffffff821115610b9557610b94610d8c565b5b602082029050602081019050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610bde82610c7b565b9150610be983610c7b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610c1e57610c1d610d2e565b5b828201905092915050565b6000610c3482610c5b565b9050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610ca3578082015181840152602081019050610c88565b83811115610cb2576000848401525b50505050565b610cc182610dbb565b810181811067ffffffffffffffff82111715610ce057610cdf610d8c565b5b80604052505050565b6000819050919050565b6000819050919050565b6000610d0882610c7b565b9150610d1383610c7b565b925082610d2357610d22610d5d565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e74726163742060008201527f7769746820666175636574000000000000000000000000000000000000000000602082015250565b7f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00600082015250565b610e4d81610c3b565b8114610e5857600080fd5b50565b610e6481610c47565b8114610e6f57600080fd5b50565b610e7b81610c51565b8114610e8657600080fd5b50565b610e9281610c7b565b8114610e9d57600080fd5b5056fea26469706673582212207e5894b476f0d46facfa4872791b634b2f715098ab3466adc631fc6f825421cb64736f6c63430008040033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file